package com.xjrsoft.module.workflow.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xjrsoft.common.Enum.DeleteMarkEnum;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.core.secure.utils.SecureUtil;
import com.xjrsoft.core.tool.utils.*;
import com.xjrsoft.module.base.entity.XjrBaseDepartment;
import com.xjrsoft.module.base.entity.XjrBaseDraft;
import com.xjrsoft.module.base.entity.XjrBaseTempfield;
import com.xjrsoft.module.base.entity.XjrBaseUser;
import com.xjrsoft.module.base.mapper.XjrBaseDraftMapper;
import com.xjrsoft.module.base.service.IXjrBaseDraftService;
import com.xjrsoft.module.base.service.IXjrBaseTempfieldService;
import com.xjrsoft.module.base.service.IXjrBaseUserRelationService;
import com.xjrsoft.module.base.service.IXjrBaseUserService;
import com.xjrsoft.module.base.utils.OrganizationCacheUtil;
import com.xjrsoft.module.base.vo.DraftVo;
import com.xjrsoft.module.form.constant.FormConstants;
import com.xjrsoft.module.form.entity.XjrFormScheme;
import com.xjrsoft.module.form.entity.XjrFormSchemeInfo;
import com.xjrsoft.module.form.service.IXjrFormSchemeInfoService;
import com.xjrsoft.module.form.service.IXjrFormSchemeService;
import com.xjrsoft.module.form.util.FormDataUtil;
import com.xjrsoft.module.form.vo.FormSchemeInfoVo;
import com.xjrsoft.module.language.entity.XjrLgMark;
import com.xjrsoft.module.language.service.IXjrLgMarkService;
import com.xjrsoft.module.oa.utils.SendMessageUtil;
import com.xjrsoft.module.workflow.dto.GetPageListNwfTaskDto;
import com.xjrsoft.module.workflow.entity.HiProcessInstance;
import com.xjrsoft.module.workflow.entity.XjrNwfRelation;
import com.xjrsoft.module.workflow.entity.XjrNwfScheme;
import com.xjrsoft.module.workflow.entity.XjrNwfSchemeinfo;
import com.xjrsoft.module.workflow.mapper.NwfTaskMapper;
import com.xjrsoft.module.workflow.service.*;
import com.xjrsoft.module.workflow.vo.NwfRelationTaskVo;
import com.xjrsoft.module.workflow.vo.TaskVo;
import io.jsonwebtoken.lang.Collections;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import oracle.sql.CLOB;
import oracle.sql.NCLOB;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class XjrNwfTaskServiceImpl implements IXjrNwfTaskService {


    private IXjrBaseUserRelationService userRelationService;

    private FormService formService;

    private IXjrNwfSchemeInfoService nwfSchemeInfoService;

    private IXjrBaseUserService userService;

    private IdentityService identityService;

    private RepositoryService repositoryService;

    private IXjrBaseTempfieldService baseTempfieldService;

    private RuntimeService runtimeService;

    private TaskService taskService;

    private HistoryService historyService;

    private RedisUtil redisUtil;

    private IXjrNwfRelationService nwfRelationService;

    private IXjrFormSchemeInfoService formSchemeInfoService;

    private IXjrFormSchemeService formSchemeService;

    private NwfTaskMapper nwfTaskMapper;

    private IXjrBaseTempfieldService xjrBaseTempfieldService;

    private IXjrBaseDraftService xjrBaseDraftService;

    private XjrBaseDraftMapper xjrBaseDraftMapper;

    private IXjrNwfSchemeService nwfSchemeService;

    private IXjrNwfSchemeInfoService nwfschemeinfoService;

    private IXjrNwfSchemeAuthService nwfSchemeAuthService;

    private IXjrLgMarkService markService;


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/21
     * @Param:[userId, dto]
     * @return:com.xjrsoft.common.page.PageOutput
     * @Description:待办任务
     */
    @Override
    public Object upcomingTasks(String userId, GetPageListNwfTaskDto dto) {
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        log.info("【查询用户 " + userId + " 的待办任务】");
        String nwfRelationId = dto.getNwfRelationId();
        String queryParameter = dto.getQueryParameter();
        // 专项菜单字段
        JSONArray formFields = nwfRelationService.getFormFieldById(nwfRelationId);
        JSONArray searchFields = nwfRelationService.getSearchFieldById(nwfRelationId, queryParameter);
        List<TaskVo> list = new ArrayList<>();
        //流水号
        String serialNumber = dto.getSerialNumber();
        JSONArray definitionKeys = nwfRelationService.getNwfSchemeInfoIds(nwfRelationId);
        JSONArray retList = new JSONArray();
        //分页标记
        IPage<TaskVo> page = nwfTaskMapper.selectBacklog(new Page<>(dto.getLimit(), dto.getSize()), dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), userId, definitionKeys);
        boolean flag = StringUtil.isNotBlank(nwfRelationId) && nwfRelationService.getPageInfoById(nwfRelationId).getString("isPage").equals("false");
        if (flag) {
            //不分页
            list = nwfTaskMapper.selectAllBacklog(dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), userId, definitionKeys);
        } else {
            list = page.getRecords();
        }
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        // 验证专项菜单模板权限
        if (!nwfRelationService.checkTemplateAuthority(nwfRelationId, userId)) {
            return ConventPage.getPageOutput(page);
        }
        Set<String> ids = list.stream().map(TaskVo::getProcessInstanceId).collect(Collectors.toSet());
        List<XjrBaseTempfield> xjrBaseTempfieldList = xjrBaseTempfieldService.getListByIdAndType(new ArrayList<>(ids), "19");
        for (TaskVo taskVo : list) {
            String taskId = taskVo.getTaskId();
            String processInstanceId = taskVo.getProcessInstanceId();
            String parentTaskId = taskVo.getParentTaskId();
            //流水号
            Optional<XjrBaseTempfield> xjrBaseTempfield = xjrBaseTempfieldList.stream().filter(x -> x.getFkey().equals(processInstanceId)).findFirst();
            xjrBaseTempfield.ifPresent(baseTempfield -> taskVo.setSerialNumber(baseTempfield.getFvalue()));
            // 不显示子任务
            if (StringUtils.isNotBlank(parentTaskId) && !StringUtils.equals(parentTaskId, "null")) {
                Task task = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
                taskId = task.getId();
            }
            // 根据流程实例ID查询流程模板名称
            // 任务发起人
            taskVo.setBtnName(taskVo.getTaskName());
            // 获取专项菜单字段
            JSONObject formFieldObj = new JSONObject();
            if (nwfRelationId != null) {
                if (nwfRelationService.checkFieldAuthority(nwfRelationId, userId, xjrBaseUserlist)) {
                    for (int j = 0; j < formFields.size(); j++) {
                        JSONObject formField = formFields.getJSONObject(j);
                        String fieldName = formField.getString("resourceId") +
                                StringPool.UNDERSCORE + formField.getString("bindTable") +
                                StringPool.UNDERSCORE + formField.getString("fieldsId");
                        Object variable = taskService.getVariable(taskId, fieldName);
                        if (variable != null) {
                            formFieldObj.put(formField.getString("name"), variable);
                        }
                    }
                    //添加搜索字段值
                    for (int j = 0; j < searchFields.size(); j++) {
                        JSONObject searchField = searchFields.getJSONObject(j);
                        String fieldName = searchField.getString("resourceId") +
                                StringPool.UNDERSCORE + searchField.getString("bindTable") +
                                StringPool.UNDERSCORE + searchField.getString("field");
                        String name = searchField.getString("name");
                        if (!formFieldObj.containsKey(name)) {
                            formFieldObj.put(name, taskService.getVariable(taskId, fieldName));
                        }
                    }
                }
            }
            taskVo.setFormFieldObj(formFieldObj);
            retList.add(taskVo);
        }
        list = queryByParam(serialNumber, queryParameter, list, searchFields);
        transFormListData(list, formFields);
        if (flag) {
            //不分页
            return list;
        }
        PageOutput<TaskVo> pageOutput = new PageOutput<>();
        pageOutput.setTotal((int) page.getTotal());
        pageOutput.setRows(list);
        return pageOutput;
    }

    @Override
    public Integer getupcomingTaskCount(String userId) {
        return nwfTaskMapper.selectAllBacklogCount(userId);
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/22
     * @Param:[userId, dto]
     * @return:com.xjrsoft.common.page.PageOutput
     * @Description:已办任务的查询
     */
    @Override
    public Object getHistoryTask(String userId, GetPageListNwfTaskDto dto) throws Exception {
        //查找缓存
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        log.info("【历史活动的查询】办理人:" + userId);
        //流水号
        String serialNumber = dto.getSerialNumber();
        String nwfRelationId = dto.getNwfRelationId();
        String queryParameter = dto.getQueryParameter();
        JSONArray definitionKeys = nwfRelationService.getNwfSchemeInfoIds(nwfRelationId);
        // 是否是单模板专项菜单
        IPage<TaskVo> page = nwfTaskMapper.selectHistoryTask(new Page<>(dto.getLimit(), dto.getSize()), dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), userId, definitionKeys);
        boolean flag = StringUtil.isNotBlank(nwfRelationId) && "false".equals(nwfRelationService.getPageInfoById(nwfRelationId).getString("isPage"));
        List<TaskVo> list = new ArrayList<>();
        if (flag) {
            //不分页
            list = nwfTaskMapper.selectAllHistoryTask(dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), userId, definitionKeys);
        } else {
            list = page.getRecords();
        }
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        JSONArray formFields = nwfRelationService.getFormFieldById(nwfRelationId);
        JSONArray searchFields = nwfRelationService.getSearchFieldById(nwfRelationId, queryParameter);
        // 验证专项菜单模板权限
        if (!nwfRelationService.checkTemplateAuthority(nwfRelationId, userId)) {
            return ConventPage.getPageOutput(page);
        }
        List<String> processInstanceIds = list.stream().map(TaskVo::getProcessInstanceId).collect(Collectors.toList());
        List<HiProcessInstance> hiProcessInstanceList = nwfTaskMapper.getHiProcessInstanceByProcessInsId(processInstanceIds);
        List<XjrBaseTempfield> xjrBaseTempfieldList = xjrBaseTempfieldService.getListByIdAndType(processInstanceIds, "19");
        List<XjrBaseTempfield> callActivityTempList = xjrBaseTempfieldService.list(new QueryWrapper<XjrBaseTempfield>().lambda().eq(XjrBaseTempfield::getType, "34"));
        for (TaskVo his : list) {
            // 获取历史任务
            String processInstanceId = his.getProcessInstanceId();
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByHistoricTaskInstanceStartTime().desc().list();
            List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().desc().list();
            HistoricActivityInstance historicActivityInstance = historicActivityInstanceList.get(0);
            if (historicProcessInstance.getEndTime() != null) {
                his.setCurrentProgress("100");
            } else if (StringUtil.equals(historicActivityInstance.getActivityType(), "callActivity")) {
                //最新节点为外部节点
                ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(his.getDeploymentId()).singleResult();
                String version = String.valueOf(processDefinition.getVersion());
                String nwfSchemeInfoId = processDefinition.getDescription();
                String key = nwfSchemeInfoId + StringPool.UNDERSCORE + historicActivityInstance.getActivityId() + StringPool.UNDERSCORE + version;
                Optional<XjrBaseTempfield> xjrBaseTempfieldOptional = callActivityTempList.stream().filter(s -> StringUtil.equals(s.getFkey(), key)).findFirst();
                if (xjrBaseTempfieldOptional.isPresent()) {
                    String fvalue = xjrBaseTempfieldOptional.get().getFvalue();
                    his.setCurrentProgress(StringUtil.equalsIgnoreCase(fvalue, "null") ? null : fvalue);
                } else {
                    his.setCurrentProgress(null);
                }
            } else if (CollectionUtil.isNotEmpty(historicTaskInstanceList)) {
                his.setCurrentProgress(historicTaskInstanceList.get(0).getDescription());
            }
            //流水号
            Optional<XjrBaseTempfield> xjrBaseTempfield = xjrBaseTempfieldList.stream().filter(x -> x.getFkey().equals(processInstanceId)).findFirst();
            xjrBaseTempfield.ifPresent(baseTempfield -> his.setSerialNumber(baseTempfield.getFvalue()));
            // 任务发起人
            Optional<HiProcessInstance> hiProcessInstanceOptional = hiProcessInstanceList.stream().filter(x -> x.getProcInstId().equals(his.getProcessInstanceId()) && StringUtil.isNotBlank(x.getStartUserId())).findFirst();
            if (hiProcessInstanceOptional.isPresent()) {
                HiProcessInstance hiProcessInstance = hiProcessInstanceOptional.get();
                String startUserId = hiProcessInstance.getStartUserId();
                Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(startUserId)).findFirst();
                xjrBaseUserOptional.ifPresent(xjrBaseUser -> his.setStartUser(xjrBaseUser != null ? xjrBaseUser.getRealName() : ""));
            }
            // 获取专项菜单字段
            JSONObject formFieldObj = new JSONObject();
            if (nwfRelationId != null) {
                if (nwfRelationService.checkFieldAuthority(nwfRelationId, userId, xjrBaseUserlist)) {
                    for (int j = 0; j < formFields.size(); j++) {
                        JSONObject formField = formFields.getJSONObject(j);
                        String fieldName = formField.getString("resourceId") + StringPool.UNDERSCORE +
                                formField.getString("bindTable") + StringPool.UNDERSCORE +
                                formField.getString("fieldsId");
                        List<HistoricVariableInstance> historicVariableInstance = historyService.createHistoricVariableInstanceQuery().variableName(fieldName).processInstanceId(processInstanceId).list();
                        for (HistoricVariableInstance variableInstance : historicVariableInstance) {
                            formFieldObj.put(formField.getString("name"), variableInstance != null ? variableInstance.getValue() : "");
                        }
                    }
                    //添加搜索字段值‘
                    for (int j = 0; j < searchFields.size(); j++) {
                        JSONObject searchField = searchFields.getJSONObject(j);
                        String fieldName = searchField.getString("resourceId") +
                                StringPool.UNDERSCORE + searchField.getString("bindTable") +
                                StringPool.UNDERSCORE + searchField.getString("field");
                        String name = searchField.getString("name");
                        if (!formFieldObj.containsKey(name)) {
                            List<HistoricVariableInstance> historicVariableInstance = historyService.createHistoricVariableInstanceQuery().variableName(fieldName).processInstanceId(processInstanceId).list();
                            for (HistoricVariableInstance variableInstance : historicVariableInstance) {
                                formFieldObj.put(name, variableInstance != null ? variableInstance.getValue() : "");
                            }
                        }
                    }
                }
            }
            his.setFormFieldObj(formFieldObj);
        }
        if (StringUtil.isNotBlank(serialNumber)) {
            Pattern pattern = Pattern.compile(serialNumber);
            list = list.stream().filter(s -> {
                Matcher matcher = pattern.matcher(s.getSerialNumber());
                //调用模糊查询方法
                if (matcher.find()) {
                    return true;
                } else {
                    return false;
                }
            }).collect(Collectors.toList());
        }
        list = queryByParam(serialNumber, queryParameter, list, searchFields);
        transFormListData(list, formFields);
        if (flag) {
            //不分页
            return list;
        }
        PageOutput<TaskVo> pageOutput = new PageOutput<>();
        pageOutput.setTotal((int) page.getTotal());
        pageOutput.setRows(list);
        return pageOutput;
    }


    @Override
    public Integer getHistoryTaskCount(String userId) {
        return nwfTaskMapper.selectHistoryTaskCount(userId);
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/12/22
     * @Param:[userId, dto]
     * @return:com.xjrsoft.common.page.PageOutput
     * @Description:
     */
    @Override
    public Object myTask(String userId, GetPageListNwfTaskDto dto) {
        //查找缓存
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        log.info("【我的任务查询】办理人:" + userId);
        //流水号
        String serialNumber = dto.getSerialNumber();
        String nwfRelationId = dto.getNwfRelationId();
        String queryParameter = dto.getQueryParameter();
        JSONArray definitionKeys = nwfRelationService.getNwfSchemeInfoIds(nwfRelationId);
        // 是否是单模板专项菜单
        List<Object> retList = new ArrayList<>();
        // 本人发起任务
        IPage<TaskVo> page = nwfTaskMapper.selectMyTask(new Page<>(dto.getLimit(), dto.getSize()), dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), userId, definitionKeys);
        boolean flag = StringUtil.isNotBlank(nwfRelationId) && nwfRelationService.getPageInfoById(nwfRelationId).getString("isPage").equals("false");
        List<TaskVo> list = new ArrayList<>();
        if (flag) {
            //不分页
            list = nwfTaskMapper.selectAllMyTask(dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), userId, definitionKeys);
        } else {
            list = page.getRecords();
        }
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        // 专项菜单字段
        JSONArray formFields = nwfRelationService.getFormFieldById(nwfRelationId);
        JSONArray searchFields = nwfRelationService.getSearchFieldById(nwfRelationId, queryParameter);
        // 验证专项菜单模板权限
        if (!nwfRelationService.checkTemplateAuthority(nwfRelationId, userId)) {
            return ConventPage.getPageOutput(page);
        }
        List<String> processInstanceIds = list.stream().map(TaskVo::getProcessInstanceId).collect(Collectors.toList());
        List<Task> taskList = taskService.createTaskQuery().processInstanceIdIn(processInstanceIds).list();
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceIdIn(processInstanceIds).list();
        List<XjrBaseTempfield> xjrBaseTempfieldList = xjrBaseTempfieldService.getListByIdAndType(processInstanceIds, "19");
        List<XjrBaseTempfield> callActivityTempList = xjrBaseTempfieldService.list(new QueryWrapper<XjrBaseTempfield>().lambda().eq(XjrBaseTempfield::getType, "34"));
        Iterator<TaskVo> iterator = list.iterator();
        while (iterator.hasNext()) {
            TaskVo taskVo = iterator.next();
            String taskId = "";
            String processInstanceId = taskVo.getProcessInstanceId();
            Optional<Task> firstTask = taskList.stream().filter(x -> x.getProcessInstanceId().equals(taskVo.getProcessInstanceId())).findFirst();
            List<HistoricTaskInstance> hiTaskList = historicTaskInstanceList.stream().sorted(Comparator.comparing(HistoricTaskInstance::getStartTime)).filter(x -> x.getProcessInstanceId().equals(taskVo.getProcessInstanceId())).collect(Collectors.toList());
            if (firstTask.isPresent()) {
                // 正在执行的任务
                Task task = firstTask.get();
                taskId = task.getId();
                // 判断是否有设置任务命名规则
                taskVo.setTaskName(task.getName());
                // 等级
                taskVo.setPriority(task.getPriority());
                // 任务id
                taskVo.setTaskId(taskId);
                if (taskVo.getEndTime() != null) {
                    taskVo.setCurrentProgress("100");
                } else {
                    taskVo.setCurrentProgress(task.getDescription());
                }
            } else {
                // 历史任务的查询
                List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(taskVo.getProcessInstanceId()).list();
                if (CollectionUtil.isNotEmpty(historicActivityInstances)) {
                    HistoricActivityInstance historicActivityInstance = historicActivityInstances.get(historicActivityInstances.size() - 1);
                    taskVo.setTaskName(historicActivityInstance.getActivityName());
                    // 等级
                    taskVo.setPriority(50);
                    // 任务id
                    if (CollectionUtil.isNotEmpty(hiTaskList)) {
                        HistoricTaskInstance historicTaskInstance = hiTaskList.get(hiTaskList.size() - 1);
                        taskVo.setTaskId(historicTaskInstance.getId());
                        taskVo.setCurrentProgress(historicTaskInstance.getDescription());
                    } else {
                        taskVo.setTaskId(historicActivityInstance.getTaskId());
                    }
                    if (taskVo.getEndTime() != null) {
                        taskVo.setCurrentProgress("100");
                    } else if (StringUtil.equals(historicActivityInstance.getActivityType(), "callActivity")) {
                        //如果当前任务为外部流程
                        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(taskVo.getDeploymentId()).singleResult();
                        String version = String.valueOf(processDefinition.getVersion());
                        String nwfSchemeInfoId = processDefinition.getDescription();
                        String key = nwfSchemeInfoId + StringPool.UNDERSCORE + historicActivityInstance.getActivityId() + StringPool.UNDERSCORE + version;
                        Optional<XjrBaseTempfield> xjrBaseTempfieldOptional = callActivityTempList.stream().filter(s -> StringUtil.equals(s.getFkey(), key)).findFirst();
                        if (xjrBaseTempfieldOptional.isPresent()) {
                            String fvalue = xjrBaseTempfieldOptional.get().getFvalue();
                            taskVo.setCurrentProgress(StringUtil.equalsIgnoreCase(fvalue, "null") ? null : fvalue);
                        } else {
                            taskVo.setCurrentProgress(null);
                        }
                    }
                }
            }
            //流水号
            Optional<XjrBaseTempfield> xjrBaseTempfield = xjrBaseTempfieldList.stream().filter(x -> x.getFkey().equals(processInstanceId)).findFirst();
            xjrBaseTempfield.ifPresent(baseTempfield -> taskVo.setSerialNumber(baseTempfield.getFvalue()));
            // 任务发起人
            Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(taskVo.getStartUser())).findFirst();
            xjrBaseUserOptional.ifPresent(xjrBaseUser -> taskVo.setStartUser(xjrBaseUser != null ? xjrBaseUser.getRealName() : ""));
            // 获取专项菜单字段
            JSONObject formFieldObj = new JSONObject();
            if (nwfRelationId != null) {
                if (nwfRelationService.checkFieldAuthority(nwfRelationId, userId, xjrBaseUserlist)) {
                    for (int j = 0; j < formFields.size(); j++) {
                        JSONObject formField = formFields.getJSONObject(j);
                        String fieldName = formField.getString("resourceId") + StringPool.UNDERSCORE +
                                formField.getString("bindTable") + StringPool.UNDERSCORE +
                                formField.getString("fieldsId");
                        HistoricVariableInstance historicVariableInstance = historyService.createHistoricVariableInstanceQuery().variableName(fieldName).processInstanceId(processInstanceId).singleResult();
                        formFieldObj.put(formField.getString("name"), historicVariableInstance != null ? historicVariableInstance.getValue() : "");
                    }
                    //添加搜索字段值‘
                    for (int j = 0; j < searchFields.size(); j++) {
                        JSONObject searchField = searchFields.getJSONObject(j);
                        String fieldName = searchField.getString("resourceId") +
                                StringPool.UNDERSCORE + searchField.getString("bindTable") +
                                StringPool.UNDERSCORE + searchField.getString("field");
                        String name = searchField.getString("name");
                        if (!formFieldObj.containsKey(name)) {
                            List<HistoricVariableInstance> historicVariableInstance = historyService.createHistoricVariableInstanceQuery().variableName(fieldName).processInstanceId(processInstanceId).list();
                            for (HistoricVariableInstance variableInstance : historicVariableInstance) {
                                formFieldObj.put(name, variableInstance != null ? variableInstance.getValue() : "");
                            }
                        }
                    }
                }
            }
            taskVo.setFormFieldObj(formFieldObj);
            retList.add(taskVo);
        }
        if (StringUtil.isNotBlank(serialNumber)) {
            Pattern pattern = Pattern.compile(serialNumber);
            list = list.stream().filter(s -> {
                Matcher matcher = pattern.matcher(s.getSerialNumber());
                //调用模糊查询方法
                return matcher.find();
            }).collect(Collectors.toList());
        }
        list = queryByParam(serialNumber, queryParameter, list, searchFields);
        transFormListData(list, formFields);
        if (flag) {
            //不分页
            return list;
        }
        PageOutput<TaskVo> pageOutput = new PageOutput<>();
        pageOutput.setTotal((int) page.getTotal());
        pageOutput.setRows(list);
        return pageOutput;
    }


    @Override
    public Integer myTaskCount(String userId) {
        return nwfTaskMapper.selectMyTaskCount(userId);
    }


    //获取我的传阅
    @Override
    public Object manualTask(String userId, GetPageListNwfTaskDto dto) {
        //查找缓存
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        List<HistoricTaskInstance> hiTaskList = historyService.createHistoricTaskInstanceQuery().taskName("传阅任务").taskAssignee(SecureUtil.getUserId()).list();
        log.info("【查询用户 " + userId + " 的传阅任务】");
        String nwfRelationId = dto.getNwfRelationId();
        String serialNumber = dto.getSerialNumber();
        String queryParameter = dto.getQueryParameter();
        JSONArray definitionKeys = nwfRelationService.getNwfSchemeInfoIds(nwfRelationId);
        List<TaskVo> taskVos = nwfTaskMapper.selectManualTask(userId);
        if (CollectionUtil.isEmpty(taskVos)) {
            return null;
        }
        ArrayList<String> ids = new ArrayList<>();
        for (TaskVo taskVo : taskVos) {
            ids.add(taskVo.getParentTaskId());
        }
        IPage<TaskVo> page = new Page<>();
        List<TaskVo> taskVos2 = new ArrayList<>();
        boolean flag = StringUtil.isNotBlank(nwfRelationId) && nwfRelationService.getPageInfoById(nwfRelationId).getString("isPage").equals("false");
        if (ids.size() > 0) {
            page = nwfTaskMapper.selectTaskByParentIds(ids, ConventPage.getPage(dto), dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), definitionKeys);
            if (flag) {
                //不分页
                taskVos2 = nwfTaskMapper.selectAllTaskByParentIds(ids, dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), definitionKeys);
            } else {
                taskVos2 = page.getRecords();
            }
            if (CollectionUtil.isEmpty(taskVos2)) {
                return null;
            }
            // 专项菜单字段
            JSONArray formFields = nwfRelationService.getFormFieldById(nwfRelationId);
            JSONArray searchFields = nwfRelationService.getSearchFieldById(nwfRelationId, queryParameter);
            // 验证专项菜单模板权限
            if (!nwfRelationService.checkTemplateAuthority(nwfRelationId, userId)) {
                return ConventPage.getPageOutput(page);
            }
            Set<String> processInstanceIds = taskVos2.stream().map(TaskVo::getProcessInstanceId).collect(Collectors.toSet());
            List<XjrBaseTempfield> xjrBaseTempfieldList = xjrBaseTempfieldService.getListByIdAndType(new ArrayList<>(processInstanceIds), "19");
            List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery().list();
            List<Task> taskList = taskService.createTaskQuery().list();
            for (TaskVo taskVo : taskVos2) {
                String taskId = taskVo.getTaskId();
                String processInstanceId = taskVo.getProcessInstanceId();
                String parentTaskId = taskVo.getParentTaskId();
                // 根据流程实例ID查询流程模板名称
                HistoricProcessInstance hisInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).orderByHistoricTaskInstanceStartTime().desc().list();
                if (hisInstance.getEndTime() != null) {
                    taskVo.setCurrentProgress("100");
                } else if (CollectionUtil.isNotEmpty(historicTaskInstanceList)) {
                    taskVo.setCurrentProgress(historicTaskInstanceList.get(0).getDescription());
                }
                Optional<HistoricTaskInstance> taskInstanceOptional = hiTaskList.stream().filter(x -> x.getParentTaskId().equals(taskVo.getTaskId())).findFirst();
                if (taskInstanceOptional.isPresent()) {
                    XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(taskInstanceOptional.get().getId(), "35");
                    taskVo.setReadState(xjrBaseTempfield != null ? 1 : 0);
                }
                //流水号
                Optional<XjrBaseTempfield> xjrBaseTempfieldOptional = xjrBaseTempfieldList.stream().filter(x -> x.getFkey().equals(processInstanceId)).findFirst();
                xjrBaseTempfieldOptional.ifPresent(xjrBaseTempfield -> taskVo.setSerialNumber(xjrBaseTempfield.getFvalue()));
                // 不显示子任务
                if (StringUtils.isNotBlank(parentTaskId) && !StringUtils.equals(parentTaskId, "null")) {
                    Optional<Task> taskOptional = taskList.stream().filter(x -> x.getId().equals(parentTaskId)).findFirst();
                    if (taskOptional.isPresent()) {
                        taskId = taskOptional.get().getId();
                    }
                }
                // 任务发起人
                if (hisInstance != null) {
                    String startUserId = hisInstance.getStartUserId();
                    Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(startUserId)).findFirst();
                    xjrBaseUserOptional.ifPresent(xjrBaseUser -> taskVo.setStartUser(xjrBaseUser != null ? xjrBaseUser.getRealName() : ""));
                    if (StringUtil.isNotBlank(hisInstance.getName())) {
                        taskVo.setSchemeName(hisInstance.getName());
                    }
                }
                // 获取节点的名称
                Optional<HistoricActivityInstance> historicActivityInstanceOptional = activityInstanceList.stream().filter(x -> x.getProcessInstanceId().equals(processInstanceId)).findFirst();
                historicActivityInstanceOptional.ifPresent(historicActivityInstance -> taskVo.setBtnName(historicActivityInstance.getActivityName()));
                // 获取专项菜单字段
                JSONObject formFieldObj = new JSONObject();
                if (nwfRelationId != null) {
                    if (nwfRelationService.checkFieldAuthority(nwfRelationId, userId, xjrBaseUserlist)) {
                        for (int j = 0; j < formFields.size(); j++) {
                            JSONObject formField = formFields.getJSONObject(j);
                            String fieldName = formField.getString("resourceId") +
                                    StringPool.UNDERSCORE + formField.getString("bindTable") +
                                    StringPool.UNDERSCORE + formField.getString("fieldsId");
                            HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(fieldName).singleResult();
                            if (variableInstance != null) {
                                formFieldObj.put(formField.getString("name"), variableInstance.getValue());
                            }
                        }
                        //添加搜索字段值‘
                        for (int j = 0; j < searchFields.size(); j++) {
                            JSONObject searchField = searchFields.getJSONObject(j);
                            String fieldName = searchField.getString("resourceId") +
                                    StringPool.UNDERSCORE + searchField.getString("bindTable") +
                                    StringPool.UNDERSCORE + searchField.getString("field");
                            String name = searchField.getString("name");
                            if (!formFieldObj.containsKey(name)) {
                                HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(fieldName).singleResult();
                                if (variableInstance != null) {
                                    formFieldObj.put(name, variableInstance.getValue());
                                }
                            }
                        }
                    }
                }
                taskVo.setFormFieldObj(formFieldObj);
            }
            taskVos2 = queryByParam(serialNumber, dto.getQueryParameter(), taskVos2, searchFields);
            transFormListData(taskVos2, formFields);
        }
        if (flag) {
            //不分页
            return taskVos2;
        }
        PageOutput<TaskVo> pageOutput = new PageOutput<>();
        pageOutput.setTotal((int) page.getTotal());
        pageOutput.setRows(taskVos2);
        return pageOutput;
    }


    @Override
    public Integer manualTaskCount(String userId) {
        List<TaskVo> taskVos = nwfTaskMapper.selectManualTask(userId);
        if (CollectionUtil.isEmpty(taskVos)) {
            return null;
        }
        ArrayList<String> ids = new ArrayList<>();
        for (TaskVo taskVo : taskVos) {
            ids.add(taskVo.getParentTaskId());
        }
        return nwfTaskMapper.selectTaskCountByParentIds(ids);
    }

    @Override
    public boolean recallProcess(String taskId, String processInstanceId) throws Exception {
        String targetActivitiId = "";
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        String deploymentId = processInstance.getDeploymentId();
        String nwfSchemeInfoId = FlowableUtil.getNwfSchemeInfoIdByDepId(deploymentId);
//        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        List<ActivityInstance> taskList = runtimeService.createActivityInstanceQuery().processInstanceId(processInstanceId).unfinished().list();
        if (StringUtil.isNotBlank(taskId)) {
            //撤回到用户任务节点
            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskId(taskId).singleResult();
            targetActivitiId = historicTaskInstance.getTaskDefinitionKey();
            Object formData = runtimeService.getVariable(processInstanceId, taskId + StringPool.UNDERSCORE + "formData");
            if (formData != null) {
                JSONArray formInfoArray = JSON.parseArray(JSON.toJSONString(formData));
                updateFormDate(formInfoArray);
            }
        } else if (StringUtil.isBlank(taskId)) {
            //撤回到开始节点
            targetActivitiId = processInstance.getStartActivityId();
        }
        ActivityInstance activityInstance = taskList.get(0);
        HistoricActivityInstance oldActivityInstance = historyService.createHistoricActivityInstanceQuery().activityId(targetActivitiId).processInstanceId(processInstanceId).list().stream().findFirst().get();
        HistoricActivityInstance nowActivityInstance = historyService.createHistoricActivityInstanceQuery().activityId(activityInstance.getActivityId()).processInstanceId(processInstanceId).list().stream().findFirst().get();
        JSONObject jsonObject = new JSONObject();
        Set<HashMap<String, Object>> nextNode = new HashSet<>();
        jsonObject.put("multiInstance", false);
        jsonObject.put("btnValue", "撤回");
        jsonObject.put("activitiId", nowActivityInstance.getActivityId());
        jsonObject.put("activityName", nowActivityInstance.getActivityName());
        String activityType = nowActivityInstance.getActivityType();
        jsonObject.put("activityType", activityType);
        if (StringUtil.equals(activityType, "callActivity")) {
            jsonObject.put("isRecall", true);
            jsonObject.put("startTime", DateUtil.now());
        } else {
            jsonObject.put("startTime", com.xjrsoft.core.tool.utils.DateUtil.format(activityInstance.getStartTime(), "yyyy-MM-dd HH:mm:ss"));
        }
        XjrBaseUser currentuser = userService.getById(SecureUtil.getUserId());
        jsonObject.put("candidate", StringUtil.isNotBlank(currentuser.getRealName()) ? currentuser.getRealName() : currentuser.getAccount());
        jsonObject.put("candidateUserId", currentuser.getUserId());
        jsonObject.put("manualinfos", new JSONArray());

        jsonObject.put("endTime", cn.hutool.core.date.DateUtil.now());
        jsonObject.put("time", cn.hutool.core.date.DateUtil.now());
        HashMap<String, Object> nextNodeInfo = new HashMap<>();
        nextNodeInfo.put("activitiId", targetActivitiId);
        nextNodeInfo.put("activityName", oldActivityInstance.getActivityName());
        nextNodeInfo.put("activityType", oldActivityInstance.getActivityType());
        nextNode.add(nextNodeInfo);
        jsonObject.put("nextNodeInfo", nextNode);
        //保存驳回记录
        XjrBaseTempfield xjrBaseTempfield = new XjrBaseTempfield();
        xjrBaseTempfield.setFkey(processInstanceId);
        xjrBaseTempfield.setFvalue(jsonObject.toJSONString());
        xjrBaseTempfield.setType("26");
        xjrBaseTempfield.setCreateTime(new Date());
        xjrBaseTempfieldService.save(xjrBaseTempfield);
        Thread.sleep(1000L);
        FlowableUtil.rollBack(processInstanceId, targetActivitiId);
        if (StringUtil.isBlank(taskId)) {
            XjrBaseTempfield startFormInfo = xjrBaseTempfieldService.getByIdAndType(processInstanceId + StringPool.UNDERSCORE + targetActivitiId, "25");
            if (startFormInfo != null) {
                Map<String, Object> formData = FlowableUtil.getFormData(startFormInfo.getFvalue(), null, nwfSchemeInfoId, deploymentId);
                runtimeService.setVariables(processInstanceId, formData);
            }
            //保存开始节点的数据到流程变量
        }
        return true;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/3
     * @Param:[processInstanceId]
     * @return:com.xjrsoft.common.page.PageOutput
     * @Description:流程流转记录
     */
    @Override
    public JSONArray historyTaskList(String processInstanceId, boolean isPersonalTask) throws Exception {
        JSONArray result = new JSONArray();
        if (StringUtil.isNotBlank(processInstanceId)) {
            HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            List<HistoricProcessInstance> historicProcessInstanceList = Arrays.asList(processInstance);
            result.addAll(getTaskList(historicProcessInstanceList, isPersonalTask, 0));
            String superProcessInstanceId = processInstance.getSuperProcessInstanceId();
            if (StringUtil.isNotBlank(superProcessInstanceId)) {
                List<HistoricProcessInstance> superHistoricProcessInstanceList = historyService.createHistoricProcessInstanceQuery().processInstanceId(superProcessInstanceId).list();
                result.addAll(getTaskList(superHistoricProcessInstanceList, isPersonalTask, 1));
            }
            List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().superProcessInstanceId(processInstanceId).list();
            result.addAll(getTaskList(list, isPersonalTask, 2));
        }
        return result;
    }

    public JSONArray getTaskList(List<HistoricProcessInstance> historicProcessInstanceList, boolean isPersonalTask, Integer type) throws Exception {
        JSONArray result = new JSONArray();
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        for (HistoricProcessInstance historicProcessInstance : historicProcessInstanceList) {
            String processInstanceId = historicProcessInstance.getId();
            //获取当前登录用户
            String loginUserId = SecureUtil.getUserId();
            JSONObject processInfo = new JSONObject();
            JSONArray retList = new JSONArray();
            // 历史任务
            List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
            list = cn.hutool.core.collection.CollectionUtil.reverse(list);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 根据实例ID查询任务发起人
            String deploymentId = historicProcessInstance.getDeploymentId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
            String version = String.valueOf(processDefinition.getVersion());
            String nwfSchemeInfoId = processDefinition.getDescription();
            //获取节点的所有流转按钮信息
            List<XjrBaseTempfield> transferBtnInfos = xjrBaseTempfieldService.list(Wrappers.<XjrBaseTempfield>query().lambda().eq(XjrBaseTempfield::getType, "2"));
            for (HistoricActivityInstance hai : list) {
                String activityType = hai.getActivityType();
                String taskId = hai.getTaskId();
                // 只返回开始节点，任务节点，结束节点,调用活动的信息
                if (StringUtils.equals(activityType, "userTask") || StringUtils.equals(activityType, "startEvent")
                        || StringUtils.equals(activityType, "endEvent") || StringUtils.equals(activityType, "callActivity")) {
                    boolean flag = false;
                    JSONArray operationInformation = new JSONArray();
                    ArrayList<String> ids = new ArrayList<>();
                    ids.add(taskId);
                    List<XjrBaseTempfield> changeCandidateList = xjrBaseTempfieldService.getListByIdAndType(ids, "38");
                    //添加转办信息
                    if (CollectionUtil.isNotEmpty(changeCandidateList)) {
                        for (XjrBaseTempfield baseTempfield : changeCandidateList) {
                            JSONObject changeCandidateObj = new JSONObject();
                            JSONObject info = new JSONObject();
                            JSONObject jsonObject = JSONObject.parseObject(baseTempfield.getFvalue());
                            String oldUserId = jsonObject.getString("oldUserId");
                            String newUserId = jsonObject.getString("newUserId");
                            XjrBaseUser oldUser = userService.getById(oldUserId);
                            XjrBaseUser newUser = userService.getById(newUserId);
                            if (oldUser != null) {
                                info.put("oldUserName", StringUtil.isNotBlank(oldUser.getRealName()) ? oldUser.getRealName() : oldUser.getAccount());
                            }
                            if (newUser != null) {
                                info.put("newUserName", StringUtil.isNotBlank(newUser.getRealName()) ? newUser.getRealName() : newUser.getAccount());
                            }
                            if (isPersonalTask && (StringUtil.equals(newUserId, loginUserId) || StringUtil.equals(oldUserId, loginUserId))) {
                                flag = true;
                            }
                            info.put("nodeName", hai.getActivityName());
                            changeCandidateObj.put("type", "transfer");
                            changeCandidateObj.put("info", info);
                            changeCandidateObj.put("createTime", baseTempfield.getCreateTime());
                            operationInformation.add(changeCandidateObj);
                        }
                    }
                    List<XjrBaseTempfield> assignCandidateList = xjrBaseTempfieldService.getListByIdAndType(ids, "39");
                    //添加审批人信息
                    if (CollectionUtil.isNotEmpty(assignCandidateList)) {
                        for (XjrBaseTempfield baseTempfield : assignCandidateList) {
                            JSONObject assignCandidateObj = new JSONObject();
                            JSONObject info = new JSONObject();
                            JSONObject jsonObject = JSONObject.parseObject(baseTempfield.getFvalue());
                            String currentUserId = jsonObject.getString("currentUserId");
                            XjrBaseUser currentUser = userService.getById(currentUserId);
                            info.put("currentUserName", currentUser != null ? currentUser.getRealName() : "");
                            JSONArray addAssigns = jsonObject.getJSONArray("addAssigns");
                            JSONArray addAssignArray = new JSONArray();
                            for (int i = 0; i < addAssigns.size(); i++) {
                                String id = addAssigns.getString(i);
                                if (isPersonalTask && StringUtil.equals(id, loginUserId)) {
                                    flag = true;
                                }
                                XjrBaseUser xjrBaseUser = userService.getById(id);
                                addAssignArray.add(xjrBaseUser != null ? xjrBaseUser.getRealName() : "");
                            }
                            info.put("addAssigns", addAssignArray);
                            info.put("nodeName", hai.getActivityName());
                            assignCandidateObj.put("info", info);
                            assignCandidateObj.put("type", "assign");
                            assignCandidateObj.put("createTime", baseTempfield.getCreateTime());
                            operationInformation.add(assignCandidateObj);
                        }
                    }
                    List<XjrBaseTempfield> delegateCandidateList = xjrBaseTempfieldService.getListByIdAndType(ids, "40");
                    //流程委托信息
                    if (CollectionUtil.isNotEmpty(delegateCandidateList)) {
                        for (XjrBaseTempfield baseTempfield : delegateCandidateList) {
                            JSONObject delegateCandidateObj = new JSONObject();
                            JSONObject info = new JSONObject();
                            JSONObject jsonObject = JSONObject.parseObject(baseTempfield.getFvalue());
                            String createUserId = jsonObject.getString("createUserId");
                            XjrBaseUser createUser = userService.getById(createUserId);
                            if (isPersonalTask && StringUtil.equals(createUserId, loginUserId)) {
                                flag = true;
                            }
                            info.put("createUserName", createUser != null ? createUser.getRealName() : "");
                            JSONArray delegateUsers = jsonObject.getJSONArray("delegateUsers");
                            JSONArray delegateUserArray = new JSONArray();
                            for (int i = 0; i < delegateUsers.size(); i++) {
                                String id = delegateUsers.getString(i);
                                if (isPersonalTask && StringUtil.equals(id, loginUserId)) {
                                    flag = true;
                                }
                                XjrBaseUser xjrBaseUser = userService.getById(id);
                                delegateUserArray.add(xjrBaseUser != null ? xjrBaseUser.getRealName() : "");
                            }
                            info.put("delegateUsers", delegateUserArray);
                            info.put("nodeName", hai.getActivityName());
                            delegateCandidateObj.put("info", info);
                            delegateCandidateObj.put("type", "delegate");
                            delegateCandidateObj.put("createTime", baseTempfield.getCreateTime());
                            operationInformation.add(delegateCandidateObj);
                        }
                    }
                    java.util.Collections.sort(operationInformation, (o1, o2) -> {
                        return (JSONObject.parseObject(JSON.toJSONString(o2))).getString("createTime").compareTo(JSONObject.parseObject(JSON.toJSONString(o1)).getString("createTime"));
                    });
                    if (CollectionUtil.isNotEmpty(operationInformation)) {
                        for (int j = 0; j < operationInformation.size(); j++) {
                            JSONObject informationJSONObject = operationInformation.getJSONObject(j);
                            JSONArray operationInformation1 = new JSONArray();
                            operationInformation1.add(informationJSONObject);
                            Date createTime = informationJSONObject.getDate("createTime");
                            Map<String, Object> map = new HashMap<String, Object>();
                            map.put("operationInformation", operationInformation1);
                            //获取下一节点的信息
                            Set<HashMap<String, Object>> nextNode = new HashSet<>();
                            String key = nwfSchemeInfoId + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + hai.getActivityId() + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + version;
                            String btnValue = "";
                            String message = "";
                            Date endTime = hai.getEndTime();
                            if (taskId != null) {
                                //获取按钮信息
                                List<Comment> taskComments = taskService.getTaskComments(taskId);
                                if (CollectionUtil.isNotEmpty(taskComments)) {
                                    Comment comment = taskComments.get(taskComments.size() - 1);
                                    JSONObject commentObj = JSONObject.parseObject(comment.getFullMessage());
                                    if (commentObj != null) {
                                        btnValue = commentObj.getString("btnValue");
                                        message = commentObj.getString("message");
                                        if (StringUtil.equals("finish_", btnValue) || StringUtil.equals("reject_", btnValue)) {
                                            //结束,驳回操作
                                            endTime = comment.getTime();
                                        }
                                    }
                                }
                            }
                            Optional<XjrBaseTempfield> transferBtnOption = transferBtnInfos.stream().filter(s -> s.getFkey().equals(key)).findFirst();
                            if (transferBtnOption.isPresent()) {
                                String transferBtnValue = transferBtnOption.get().getFvalue();
                                JSONArray btnArry = JSONArray.parseArray(transferBtnValue);
                                for (int i = 0; i < btnArry.size(); i++) {
                                    JSONObject btnObject = btnArry.getJSONObject(i);
                                    if (btnObject.getString("val").equals(btnValue)) {
                                        String btnKey = btnObject.getString("key");
                                        XjrLgMark lgMarkByCode = markService.getLgMarkByCode(btnKey);
                                        btnValue = lgMarkByCode != null ? lgMarkByCode.getName() : btnKey;
                                        break;
                                    }
                                }
                            }
                            boolean multiInstance = false;
                            if (taskId != null) {
                                multiInstance = FlowableUtil.isMultiInstance(taskId);
                            }
                            String deleteReason = hai.getDeleteReason();
                            if (deleteReason != null) {
                                String[] tos = deleteReason.split("to ");
                                if (tos != null && tos.length > 1) {
                                    String targetId = tos[1];
                                    HashMap<String, Object> nextNodeInfo = new HashMap<>();
                                    Optional<HistoricActivityInstance> first = list.stream().filter(s -> StringUtil.equals(targetId, s.getActivityId())).findFirst();
                                    if (first.isPresent()) {
                                        HistoricActivityInstance historicActivityInstance = first.get();
                                        nextNodeInfo.put("activitiId", historicActivityInstance.getActivityId());
                                        nextNodeInfo.put("activityName", historicActivityInstance.getActivityName());
                                        nextNodeInfo.put("activityType", historicActivityInstance.getActivityType());
                                        nextNode.add(nextNodeInfo);
                                    }
                                }
                            } else {
                                nextNode = FlowableUtil.getUsetTaskNode(hai.getActivityId(), processInstanceId, 1);
                            }
                            map.put("multiInstance", multiInstance);
                            map.put("btnValue", btnValue);
                            map.put("message", message);
                            map.put("nextNodeInfo", nextNode);
                            map.put("activitiId", hai.getActivityId());
                            map.put("activityName", hai.getActivityName());
                            Optional<Object> objectOptional = retList.stream().filter(s -> StringUtil.equals((String.valueOf(((Map<String, Object>) s).get("activitiId"))), hai.getActivityId())).findFirst();
                            if (objectOptional.isPresent() && StringUtil.equals(activityType, "startEvent")) {
                                map.put("activityType", "againStart");
                            } else {
                                map.put("activityType", activityType);
                            }
                            JSONArray allmanualinfo = getAllmanualinfo(hai.getActivityId(), deploymentId, processInstanceId);
                            for (int i = 0; i < allmanualinfo.size(); i++) {
                                JSONObject allmanualinfoObj = allmanualinfo.getJSONObject(i);
                                String userId = allmanualinfoObj.getString("userId");
                                if (isPersonalTask && StringUtil.equals(userId, loginUserId)) {
                                    flag = true;
                                }
                            }
                            map.put("manualinfos", allmanualinfo);
                            // 获取当前任务的候选人
                            List<String> condidateUsers = new ArrayList<>();
                            if (StringUtils.isNotBlank(taskId)) {
                                if (StringUtil.isNotBlank(hai.getAssignee())) {
                                    Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(hai.getAssignee())).findFirst();
                                    if (xjrBaseUserOptional.isPresent()) {
                                        String fRealname = xjrBaseUserOptional.get().getRealName();
                                        condidateUsers.add(StringUtil.isNotBlank(fRealname) ? fRealname : xjrBaseUserOptional.get().getAccount());
                                        if (isPersonalTask && StringUtil.equals(xjrBaseUserOptional.get().getUserId(), loginUserId)) {
                                            flag = true;
                                        }
                                    }
                                } else {
                                    List<HistoricIdentityLink> userList = historyService.getHistoricIdentityLinksForTask(taskId);
                                    for (int i = 0; i < userList.size(); i++) {
                                        String userType = userList.get(i).getType();
                                        String userId = userList.get(i).getUserId();
                                        Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(userId)).findFirst();
                                        if (xjrBaseUserOptional.isPresent()) {
                                            String fRealname = xjrBaseUserOptional.get().getRealName();
                                            if ("candidate".equals(userType)) {
                                                condidateUsers.add(StringUtil.isNotBlank(fRealname) ? fRealname : xjrBaseUserOptional.get().getAccount());
                                                if (isPersonalTask && StringUtil.equals(xjrBaseUserOptional.get().getUserId(), loginUserId)) {
                                                    flag = true;
                                                }
                                            }
                                        }
                                    }
                                }
                                String candidateUsers = condidateUsers.toString().replace("[", "").replace("]", "");
                                map.put("candidate", candidateUsers);
                            }
                            // 开始时间
                            Date startTime = hai.getStartTime();
                            Object startDate = null;
                            if (startTime != null) {
                                startDate = simpleDateFormat.format(startTime);
                            }
                            map.put("startTime", startDate);
                            // 结束时间
                            Object endDate = null;
                            if (endTime != null) {
                                endDate = simpleDateFormat.format(endTime);
                            }
                            map.put("endTime", endDate);
                            // tim
                            Date time = createTime;
                            if (time == null) {
                                time = endTime;
                            }
                            if (time == null || StringUtil.equals(activityType, "callActivity")) {
                                time = hai.getStartTime();
                            }
                            Object timeDate = simpleDateFormat.format(time);
                            map.put("time", timeDate);
                            // 任务发起人
                            String startUserId = "";
                            if (StringUtil.equals(activityType, "startEvent") && hai.getAssignee() != null) {
                                startUserId = hai.getAssignee();
                                if (isPersonalTask && StringUtil.equals(startUserId, loginUserId)) {
                                    flag = true;
                                }
                            } else if (StringUtil.equals(activityType, "callActivity")) {
                                String calledProcessInstanceId = hai.getCalledProcessInstanceId();
                                HistoricProcessInstance calledProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(calledProcessInstanceId).singleResult();
                                if (calledProcessInstance != null) {
                                    startUserId = calledProcessInstance.getStartUserId();
                                    if (isPersonalTask && StringUtil.equals(startUserId, loginUserId)) {
                                        flag = true;
                                    }
                                }
                            } else {
                                startUserId = historicProcessInstance.getStartUserId();
                            }
                            String finalStartUserId = startUserId;
                            Optional<XjrBaseUser> userOptional = xjrBaseUserlist.stream().filter(s -> StringUtil.equals(s.getUserId(), finalStartUserId)).findFirst();
                            if (userOptional.isPresent()) {
                                XjrBaseUser startUser = userOptional.get();
                                map.put("startUserId", StringUtil.isNotBlank(startUser.getRealName()) ? startUser.getRealName() : startUser.getAccount());
                            }
                            if (isPersonalTask && !flag) {
                                continue;
                            }
                            if (!("userTask".equals(activityType) && StringUtil.isBlank(btnValue) && endTime != null)) {
                                retList.add(map);
                            }
                        }
                    } else {
                        Map<String, Object> map = new HashMap<String, Object>();
                        Set<HashMap<String, Object>> nextNode = new HashSet<>();
                        String key = nwfSchemeInfoId + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + hai.getActivityId() + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + version;
                        String btnValue = "";
                        String message = "";
                        Date endTime = hai.getEndTime();
                        if (taskId != null) {
                            //获取按钮信息
                            List<Comment> taskComments = taskService.getTaskComments(taskId);
                            if (CollectionUtil.isNotEmpty(taskComments)) {
                                Comment comment = taskComments.get(taskComments.size() - 1);
                                JSONObject commentObj = JSONObject.parseObject(comment.getFullMessage());
                                if (commentObj != null) {
                                    btnValue = commentObj.getString("btnValue");
                                    message = commentObj.getString("message");
                                    if (StringUtil.equals("finish_", btnValue) || StringUtil.equals("reject_", btnValue)) {
                                        //结束操作
                                        endTime = comment.getTime();
                                    }
                                }
                            }
                        }
                        Optional<XjrBaseTempfield> transferBtnOption = transferBtnInfos.stream().filter(s -> s.getFkey().equals(key)).findFirst();
                        if (transferBtnOption.isPresent()) {
                            String transferBtnValue = transferBtnOption.get().getFvalue();
                            JSONArray btnArry = JSONArray.parseArray(transferBtnValue);
                            for (int i = 0; i < btnArry.size(); i++) {
                                JSONObject btnObject = btnArry.getJSONObject(i);
                                if (btnObject.getString("val").equals(btnValue)) {
                                    String btnKey = btnObject.getString("key");
                                    XjrLgMark lgMarkByCode = markService.getLgMarkByCode(btnKey);
                                    btnValue = lgMarkByCode != null ? lgMarkByCode.getName() : btnKey;
                                    break;
                                }
                            }
                        }
                        boolean multiInstance = false;
                        if (taskId != null) {
                            multiInstance = FlowableUtil.isMultiInstance(taskId);
                        }
                        String deleteReason = hai.getDeleteReason();
                        if (deleteReason != null) {
                            String[] tos = deleteReason.split("to ");
                            if (tos != null && tos.length > 1) {
                                String targetId = tos[1];
                                HashMap<String, Object> nextNodeInfo = new HashMap<>();
                                Optional<HistoricActivityInstance> first = list.stream().filter(s -> StringUtil.equals(targetId, s.getActivityId())).findFirst();
                                if (first.isPresent()) {
                                    HistoricActivityInstance historicActivityInstance = first.get();
                                    nextNodeInfo.put("activitiId", historicActivityInstance.getActivityId());
                                    nextNodeInfo.put("activityName", historicActivityInstance.getActivityName());
                                    nextNodeInfo.put("activityType", historicActivityInstance.getActivityType());
                                    nextNode.add(nextNodeInfo);
                                }
                            }
                        } else {
                            nextNode = FlowableUtil.getUsetTaskNode(hai.getActivityId(), processInstanceId, 1);
                        }
                        map.put("multiInstance", multiInstance);
                        map.put("btnValue", btnValue);
                        map.put("message", message);
                        map.put("nextNodeInfo", nextNode);
                        map.put("activitiId", hai.getActivityId());
                        map.put("activityName", hai.getActivityName());
                        String assignee = hai.getAssignee();
                        if (StringUtil.isBlank(assignee) && StringUtil.equals(activityType, "startEvent")) {
                            map.put("activityType", "againStart");
                        } else {
                            map.put("activityType", activityType);
                        }
                        JSONArray allmanualinfo = getAllmanualinfo(hai.getActivityId(), deploymentId, processInstanceId);
                        for (int i = 0; i < allmanualinfo.size(); i++) {
                            JSONObject allmanualinfoObj = allmanualinfo.getJSONObject(i);
                            String userId = allmanualinfoObj.getString("userId");
                            if (isPersonalTask && StringUtil.equals(userId, loginUserId)) {
                                flag = true;
                            }
                        }
                        map.put("manualinfos", allmanualinfo);
                        // 获取当前任务的候选人
                        List<String> condidateUsers = new ArrayList<>();
                        if (StringUtils.isNotBlank(taskId)) {
                            if (StringUtil.isNotBlank(hai.getAssignee())) {
                                Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(hai.getAssignee())).findFirst();
                                if (xjrBaseUserOptional.isPresent()) {
                                    String fRealname = xjrBaseUserOptional.get().getRealName();
                                    condidateUsers.add(StringUtil.isNotBlank(fRealname) ? fRealname : xjrBaseUserOptional.get().getAccount());
                                    if (isPersonalTask && StringUtil.equals(loginUserId, xjrBaseUserOptional.get().getUserId())) {
                                        flag = true;
                                    }
                                }
                            } else {
                                List<HistoricIdentityLink> userList = historyService.getHistoricIdentityLinksForTask(taskId);
                                for (int i = 0; i < userList.size(); i++) {
                                    String userType = userList.get(i).getType();
                                    String userId = userList.get(i).getUserId();
                                    Optional<XjrBaseUser> xjrBaseUserOptional = xjrBaseUserlist.stream().filter(x -> x.getUserId().equals(userId)).findFirst();
                                    if (xjrBaseUserOptional.isPresent()) {
                                        String fRealname = xjrBaseUserOptional.get().getRealName();
                                        if ("candidate".equals(userType)) {
                                            condidateUsers.add(StringUtil.isNotBlank(fRealname) ? fRealname : xjrBaseUserOptional.get().getAccount());
                                            if (isPersonalTask && StringUtil.equals(loginUserId, xjrBaseUserOptional.get().getUserId())) {
                                                flag = true;
                                            }
                                        }
                                    }
                                }
                            }
                            String candidateUsers = condidateUsers.toString().replace("[", "").replace("]", "");
                            map.put("candidate", candidateUsers);
                        }
                        // 开始时间
                        Date startTime = hai.getStartTime();
                        Object startDate = null;
                        if (startTime != null) {
                            startDate = simpleDateFormat.format(startTime);
                        }
                        map.put("startTime", startDate);
                        // 结束时间
                        Object endDate = null;
                        if (endTime != null) {
                            endDate = simpleDateFormat.format(endTime);
                        }
                        map.put("endTime", endDate);
                        // tim
                        Date time = endTime;
                        if (time == null || StringUtil.equals(activityType, "callActivity")) {
                            time = hai.getStartTime();
                        }
                        Object timeDate = simpleDateFormat.format(time);
                        map.put("time", timeDate);
                        // 任务发起人
                        String startUserId = "";
                        if (StringUtil.equals(activityType, "startEvent") && hai.getAssignee() != null) {
                            startUserId = hai.getAssignee();
                            if (isPersonalTask && StringUtil.equals(startUserId, loginUserId)) {
                                flag = true;
                            }
                        } else if (StringUtil.equals(activityType, "callActivity")) {
                            String calledProcessInstanceId = hai.getCalledProcessInstanceId();
                            HistoricProcessInstance calledProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(calledProcessInstanceId).singleResult();
                            if (calledProcessInstance != null) {
                                startUserId = calledProcessInstance.getStartUserId();
                                if (isPersonalTask && StringUtil.equals(startUserId, loginUserId)) {
                                    flag = true;
                                }
                            }
                        } else {
                            startUserId = historicProcessInstance.getStartUserId();
                        }
                        String finalStartUserId = startUserId;
                        Optional<XjrBaseUser> userOptional = xjrBaseUserlist.stream().filter(s -> StringUtil.equals(s.getUserId(), finalStartUserId)).findFirst();
                        if (userOptional.isPresent()) {
                            XjrBaseUser startUser = userOptional.get();
                            if (StringUtil.equals(activityType, "startEvent") && StringUtil.equals(loginUserId, startUser.getUserId())) {
                                flag = true;
                            }
                            map.put("startUserId", StringUtil.isNotBlank(startUser.getRealName()) ? startUser.getRealName() : startUser.getAccount());
                        }
                        if (isPersonalTask && !flag) {
                            continue;
                        }
                        if (!("userTask".equals(activityType) && StringUtil.isBlank(btnValue) && endTime != null)) {
                            retList.add(map);
                        }
                    }
                } else if (StringUtil.equals("scriptTask", activityType)) {
                    XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(processInstanceId + StringPool.UNDERSCORE + hai.getActivityId(), "37");
                    //脚本任务
                    if (xjrBaseTempfield != null) {
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("activitiId", hai.getActivityId());
                        map.put("activityName", hai.getActivityName());
                        map.put("activityType", hai.getActivityType());
                        map.put("startTime", simpleDateFormat.format(hai.getStartTime()));
                        map.put("endTime", simpleDateFormat.format(hai.getEndTime()));
                        map.put("time", simpleDateFormat.format(hai.getEndTime()));
                        map.put("scriptTexts", xjrBaseTempfield.getFvalue());
                        retList.add(map);
                    }
                }
            }
            List<XjrBaseTempfield> xjrBaseTempfieldList = new ArrayList<>();
            xjrBaseTempfieldList.addAll(xjrBaseTempfieldService.list(Wrappers.<XjrBaseTempfield>query().lambda().eq(XjrBaseTempfield::getFkey, processInstanceId).eq(XjrBaseTempfield::getType, "26")));
            xjrBaseTempfieldList.addAll(xjrBaseTempfieldService.list(Wrappers.<XjrBaseTempfield>query().lambda().eq(XjrBaseTempfield::getFkey, processInstanceId).eq(XjrBaseTempfield::getType, "41")));
            xjrBaseTempfieldList.addAll(xjrBaseTempfieldService.list(Wrappers.<XjrBaseTempfield>query().lambda().eq(XjrBaseTempfield::getFkey, processInstanceId).eq(XjrBaseTempfield::getType, "42")));
            if (CollectionUtil.isNotEmpty(xjrBaseTempfieldList)) {
                for (XjrBaseTempfield xjrBaseTempfield : xjrBaseTempfieldList) {
                    JSONObject jsonObject = JSONObject.parseObject(xjrBaseTempfield.getFvalue());
                    String candidateUserId = jsonObject.getString("candidateUserId");
                    if ((isPersonalTask && StringUtil.equals(loginUserId, candidateUserId)) || !isPersonalTask) {
                        retList.add(jsonObject);
                    }
                }
            }
            java.util.Collections.sort(retList, (o1, o2) -> {
                return (JSONObject.parseObject(JSON.toJSONString(o2))).getString("time").compareTo(JSONObject.parseObject(JSON.toJSONString(o1)).getString("time"));
            });
            String name = historicProcessInstance.getName();
            processInfo.put("processName", name);
            processInfo.put("taskList", retList);
            processInfo.put("processType", type);
            result.add(processInfo);
        }
        return result;
    }

    public boolean updateFormDate(JSONArray formInfoArray) throws Exception {
        for (int i = 0; i < formInfoArray.size(); i++) {
            JSONObject formInfoObj = formInfoArray.getJSONObject(i);
            JSONObject formInfo = formInfoObj.getJSONObject("formInfo");
            JSONObject formData = formInfoObj.getJSONObject("formData");
            Integer type = formInfo.getInteger("F_Type");
            if (type == 0) {
                //自定义表单
                String fId = formInfo.getString("F_Id");
                String formId = formInfo.getString("F_FormId");
                formSchemeInfoService.updateCustomFormData(formId, fId, formData);
            } else if (type == 2) {
                String fId = formInfo.getString("F_Id");
                String urlAddress = formInfo.getString("F_UrlAddress");
                FlowableUtil.updateSystemFormData(fId, urlAddress, formData);
            }
        }
        return true;
    }


    @Override
    public JSONArray getAllmanualinfo(String actId, String deploymentId, String processInstanceId) throws Exception {
        //获取传阅人信息
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
        String version = String.valueOf(processDefinition.getVersion());
        String nwfSchemeInfoId = processDefinition.getDescription();
        String key = nwfSchemeInfoId + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + actId + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + version;
        XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(key, "7");
        //追加传阅人
        XjrBaseTempfield xjrBaseTempfield1 = xjrBaseTempfieldService.getByIdAndType(processInstanceId + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + actId, "7");
        JSONArray manualinfos = new JSONArray();
        JSONArray jsonArray = new JSONArray();
        if (xjrBaseTempfield != null) {
            String fvalue = xjrBaseTempfield.getFvalue();
            if (fvalue != null) {
                jsonArray.addAll(JSONArray.parseArray(fvalue));
            }
        }
        if (xjrBaseTempfield1 != null) {
            String fvalue = xjrBaseTempfield1.getFvalue();
            if (fvalue != null) {
                jsonArray.addAll(JSONArray.parseArray(fvalue));
            }
        }
        if (CollectionUtil.isNotEmpty(jsonArray)) {
            List<HistoricActivityInstance> histList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).orderByHistoricActivityInstanceStartTime().asc().list();
            Set<String> userIds = FlowableUtil.checkUsers(processInstanceId, histList, jsonArray);
            for (String userId : userIds) {
                Optional<XjrBaseUser> first = xjrBaseUserlist.stream().filter(s -> StringUtil.equals(s.getUserId(), userId)).findFirst();
                if (first.isPresent()) {
                    XjrBaseUser user = first.get();
                    JSONObject manualinfo = new JSONObject();
                    XjrBaseDepartment xjrBaseDepartment = new XjrBaseDepartment();
                    List<XjrBaseDepartment> xjrBaseDepartments = userService.queryDepartmentsOfUser(user.getUserId());
                    if (CollectionUtil.isNotEmpty(xjrBaseDepartments)) {
                        xjrBaseDepartment = xjrBaseDepartments.get(0);
                    }
                    String account = "";
                    if (StringUtil.isNotBlank(user.getRealName())) {
                        account = user.getRealName();
                    } else {
                        account = user.getAccount();
                    }
                    manualinfo.put("userId", user.getUserId());
                    manualinfo.put("account", account);
                    manualinfo.put("departmentName", xjrBaseDepartment.getFullName());
                    manualinfos.add(manualinfo);
                }
            }
        }
        return manualinfos;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2021/1/19
     * @Param:[dto, userId]
     * @return:com.xjrsoft.common.page.PageOutput
     * @Description:获取关联任务
     */
    @Override
    public PageOutput getRelationTask(GetPageListNwfTaskDto dto, String userId) {
        Page<NwfRelationTaskVo> page = new Page<>();
        String relevanceTaskStr = dto.getRelevanceTask();
        JSONObject relevanceTask = JSON.parseObject(relevanceTaskStr);
        if (relevanceTask != null) {
            //流程的状态
            String tStatu = relevanceTask.getString("tStatu");
            Integer statu = null;
            switch (tStatu) {
                case "ongoing":
                    statu = 1;
                    break;
                case "approveAdopt":
                    statu = 2;
                    break;
            }
            String tAuthority = relevanceTask.getString("tAuthority");
            Integer authority = null;
            switch (tAuthority) {
                case "all":
                    authority = 1;
                    break;
                case "createUser":
                    authority = 2;
                    break;
            }
            String deploymentId = relevanceTask.getString("F_DeploymentId");
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
            page = nwfTaskMapper.getRelationTask(new Page(dto.getLimit(), dto.getSize()), dto.getStartTime(), dto.getEndTime(), dto.getKeyword(), processDefinition.getKey(), SecureUtil.getUserId(), statu, authority);
        }
        return ConventPage.getPageOutput(page);
    }

    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/11/10
     * @Param:[processInstanceId]
     * @return:com.alibaba.fastjson.JSONObject
     * @Description:获取关联流程任务信息
     */
    @SneakyThrows
    @Override
    public JSONObject getRelationTaskInfo(String processInstanceId) {
        JSONObject retObject = new JSONObject();
        String businessKey = "";
        String taskId = "";
        String deploymentId = "";
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance != null) {
            Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).list().get(0);
            taskId = task.getId();
            businessKey = processInstance.getBusinessKey();
            deploymentId = processInstance.getDeploymentId();

        } else {
            HistoricProcessInstance hisProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            HistoricTaskInstance hisTask = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list().get(0);
            taskId = hisTask.getId();
            businessKey = hisProcessInstance.getBusinessKey();
            deploymentId = hisProcessInstance.getDeploymentId();
        }
        // 表单信息
        String[] formIds = FlowableUtil.readTaskForm(taskId);
        List<XjrFormSchemeInfo> xjrFormSchemeInfos = formSchemeInfoService.listByIds(Arrays.asList(formIds));
        List<XjrFormScheme> xjrFormSchemes = formSchemeService.listByIds(xjrFormSchemeInfos.stream().map(XjrFormSchemeInfo::getSchemeId).collect(Collectors.toSet()));
        JSONArray formAry = new JSONArray();
        if (formIds != null) {
            for (String formId : formIds) {
                JSONObject map = new JSONObject();
                // 获取表单配置
                XjrFormSchemeInfo xjrFormSchemeInfo = xjrFormSchemeInfos.stream().filter(s -> s.getId().equals(formId)).findAny().orElse(null);
                map.put("schemeInfo", BeanUtil.copy(xjrFormSchemeInfo, FormSchemeInfoVo.class));
                Integer type = xjrFormSchemeInfo.getType();
                if (type == 0) {
                    XjrFormScheme scheme = xjrFormSchemes.stream().filter(s -> s.getId().equals(xjrFormSchemeInfo.getSchemeId())).findAny().orElse(null);
                    JSONObject schemeJson = JSONObject.parseObject(scheme.getScheme());
                    map.put("formScheme", schemeJson);
                } else {
                    String fullUrlAddress = formSchemeInfoService.getFullUrlOfSystemForm(formId);
                    map.put("F_UrlAddress", fullUrlAddress);
                }
                // 表单数据
                if (StringUtils.isNotBlank(businessKey)) {
                    // bussinessKey:[{"F_Id":"q44s577Aq1","F_FormId":"w632879Cw1"},{"F_Id":"1g5GgR3t49","F_FormId":"a23c82bb-e0a4-4f20-8b7b-efac542b8be3"}]
                    JSONArray keyList = JSONObject.parseArray(businessKey);
                    for (int i = 0; i < keyList.size(); i++) {
                        JSONObject keyMap = keyList.getJSONObject(i);
                        // 表单id相等
                        if (StringUtils.equalsIgnoreCase(formId, keyMap.getString("F_FormId"))) {
                            // 该表单的keyValue
                            String value = keyMap.getString("F_Id");
                            // 获取这个表单的数据
                            Map<String, Object> formData = null;
                            if (type == 0) {
                                formData = formSchemeInfoService.getCustomFormData(formId, value);
                            } else {
                                String urlAddress = keyMap.getString("F_UrlAddress");
                                formData = FlowableUtil.getSystemFormData(value, urlAddress);
                            }
                            map.put("formData", formData);
                        }
                    }
                }
                formAry.add(map);
            }
        }
        // 表单信息
        retObject.put("formInfo", formAry);
        // 流转记录
        retObject.put("historyTaskList", historyTaskList(processInstanceId, false));
        return retObject;
    }


    /**
     * @Author:湘北智造-框架开发组
     * @Date:2020/10/23
     * @Param:[processInstanceId, deploymentId]
     * @return:void
     * @Description:判断当前任务是否有·人
     */
    public void checkManualUser(String processInstanceId, String deploymentId) throws Exception {
        String nwfSchemeInfoId = "";
        String version = FlowableUtil.getVersionByDepId(deploymentId);
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (processInstance != null) {
            String processDefinitionId = processInstance.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
            if (processDefinition != null) {
                nwfSchemeInfoId = processDefinition.getDescription();
            }
        }
        if (Collections.isEmpty(taskList)) {
            Task task = taskList.get(0);
            // 获取当前任务的节点
            String resourceId = task.getTaskDefinitionKey();
            String key = nwfSchemeInfoId + "_" + resourceId + "_" + version;
            XjrBaseTempfield xjrTempKeyvalue = baseTempfieldService.getByIdAndType(key, "6");
            if (xjrTempKeyvalue != null) {
                String colValue = xjrTempKeyvalue.getFvalue();
//                saveManualInfo(task.getId(), colValue);
            }
        }
    }


    @Override
    public boolean saveOrEditTempfiledInfo(JSONObject parameter) throws Exception {
        String schemeinfoId = parameter.getString("F_SchemeinfoId");
        String deploymentId = parameter.getString("F_DeploymentId");
        String fId = parameter.getString("F_Id");
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfSchemeInfoService.getById(schemeinfoId);
        if (xjrNwfSchemeinfo == null) {
            throw new Exception("模板信息不存在!!!");
        }
        if (StringUtil.isBlank(fId)) {
            //新增
            XjrBaseDraft xjrBaseDraft = new XjrBaseDraft();
            JSONArray data = parameter.getJSONArray("data");
            String dataInfo = data.toString();
            xjrBaseDraft.setValue(dataInfo);
            xjrBaseDraft.setDeploymentId(deploymentId);
            xjrBaseDraft.setModifyUserId(SecureUtil.getUserId());
            xjrBaseDraft.setModifyUserName(SecureUtil.getUserName());
            xjrBaseDraft.setDeleteMark(DeleteMarkEnum.NODELETE.getCode());
            xjrBaseDraft.setSchemeinfoId(schemeinfoId);
            xjrBaseDraft.setSchemeinfoName(xjrNwfSchemeinfo.getName());
            return xjrBaseDraftService.save(xjrBaseDraft);
        } else {
            //编辑
            XjrBaseDraft xjrBaseDraft = xjrBaseDraftService.getById(fId);
            if (xjrBaseDraft != null) {
                JSONArray data = parameter.getJSONArray("data");
                String dataInfo = data.toString();
                xjrBaseDraft.setValue(dataInfo);
                return xjrBaseDraftService.updateById(xjrBaseDraft);
            }
        }
        return false;
    }

    @Override
    public Object getTempfiledInfoList(GetPageListNwfTaskDto dto) {
        List<XjrBaseUser> xjrBaseUserlist = OrganizationCacheUtil.getListCaches(OrganizationCacheUtil.USER_LIST_CACHE_KEY);
        String nwfRelationId = dto.getNwfRelationId();
        // 专项菜单字段
        JSONArray formFields = nwfRelationService.getFormFieldById(nwfRelationId);
        List<XjrBaseDraft> list = new ArrayList<>();
        XjrNwfRelation xjrNwfRelation = nwfRelationService.getById(StringUtil.isBlank(nwfRelationId) ? "" : nwfRelationId);
        ArrayList<String> nwfSchemeInfoIds = new ArrayList<>();
        if (xjrNwfRelation != null) {
            String settingJson = xjrNwfRelation.getSettingJson();
            if (StringUtil.isNotBlank(settingJson)) {
                JSONObject jsonObject = JSONObject.parseObject(settingJson);
                JSONArray stepArrays = jsonObject.getJSONArray("step2");
                for (int i = 0; i < stepArrays.size(); i++) {
                    nwfSchemeInfoIds.add(stepArrays.getJSONObject(i).getString("F_Id"));
                }
            }
        }
        LambdaQueryWrapper<XjrBaseDraft> wrapper = Wrappers.<XjrBaseDraft>query().lambda().in(CollectionUtil.isNotEmpty(nwfSchemeInfoIds), XjrBaseDraft::getSchemeinfoId, nwfSchemeInfoIds).eq(XjrBaseDraft::getDeleteMark, DeleteMarkEnum.NODELETE.getCode()).like(XjrBaseDraft::getSchemeinfoName, dto.getKeyword());
        if (!SecureUtil.isAdminUser()) {
            //如果不是管理员
            wrapper = wrapper.eq(XjrBaseDraft::getCreateUserId, SecureUtil.getUserId());
        }
        wrapper = wrapper.orderByDesc(XjrBaseDraft::getModifyDate);
        IPage<XjrBaseDraft> xjrBaseDraftIPage = xjrBaseDraftMapper.selectPage(new Page<>(dto.getLimit(), dto.getSize()), wrapper);
        boolean flag = StringUtil.isNotBlank(nwfRelationId) && nwfRelationService.getPageInfoById(nwfRelationId).getString("isPage").equals("false");
        if (flag) {
            //不分页
            list = xjrBaseDraftMapper.selectList(wrapper);
        } else {
            list = xjrBaseDraftIPage.getRecords();
        }
        // 验证专项菜单模板权限
        if (!nwfRelationService.checkTemplateAuthority(nwfRelationId, SecureUtil.getUserId())) {
            return ConventPage.getPageOutput(xjrBaseDraftIPage);
        }
        List<DraftVo> draftVos = BeanUtil.copyList(list, DraftVo.class);
        for (DraftVo draftVo : draftVos) {
            JSONObject formFieldObj = new JSONObject();
            if (nwfRelationId != null) {
                if (nwfRelationService.checkFieldAuthority(nwfRelationId, SecureUtil.getUserId(), xjrBaseUserlist)) {
                    for (int j = 0; j < formFields.size(); j++) {
                        JSONObject formField = formFields.getJSONObject(j);
                        String fieldName = formField.getString("resourceId") +
                                StringPool.UNDERSCORE + formField.getString("bindTable") +
                                StringPool.UNDERSCORE + formField.getString("fieldsId");
//                        formFieldObj.put(formField.getString("name"), taskService.getVariable(taskId, fieldName));
                    }
                }
            }
            draftVo.setFormFieldObj(formFieldObj);
        }
        if (flag) {
            return draftVos;
        } else {
            PageOutput<DraftVo> objectPageOutput = new PageOutput<>();
            objectPageOutput.setTotal((int) xjrBaseDraftIPage.getTotal());
            objectPageOutput.setRows(draftVos);
            return objectPageOutput;
        }
    }

    @Override
    public boolean deleteTempfiledInfo(String fId) {
        return xjrBaseDraftService.removeById(fId);
    }

    @Override
    public Map<String, String> getTaskInfo(String taskId, String operation) throws Exception {
        String userId = SecureUtil.getUserId();
        //流程状态
        String isNormal = "";
        String isApproval = "";
        String isRights = "";
        String processInstanceId = "";
        String schemeName = "";
        String taskName = "";
        String startUser = "";
        String createTime = "";
//        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new Exception("任务不存在");
        }
        processInstanceId = task.getProcessInstanceId();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).processInstanceId(processInstanceId).singleResult();
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if ("1".equals(operation)) {
            //审批操作
            if ("删除".equals(historicProcessInstance.getDeleteReason()) || processInstance == null || processInstance.isSuspended()) {
                isNormal = "0";
            } else {
                isNormal = "1";
                //获取所有审批人
                List<String> userIds = nwfTaskMapper.getUserIdByRunTask(taskId);
                if (!userIds.contains(userId)) {
                    isRights = "0";
                } else {
                    isRights = "1";
                }
                if (task.getEndTime() != null) {
                    isApproval = "1";
                } else {
                    isApproval = "0";
                }
                schemeName = processInstance.getProcessDefinitionName();
                taskName = task.getName();
                startUser = userService.getById(processInstance.getStartUserId()).getAccount();
                createTime = DateUtil.formatDate(processInstance.getStartTime());
            }
        } else {
            //传阅操作
            if ("删除".equals(historicProcessInstance.getDeleteReason()) || processInstance == null || processInstance.isSuspended()) {
                isNormal = "0";
            } else {
                isNormal = "1";
                //获取所有传阅人
                String version = FlowableUtil.getVersionByDepId(historicProcessInstance.getDeploymentId());
                ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(historicProcessInstance.getProcessDefinitionId()).singleResult();
                String nwfSchemeInfoId = processDefinition.getDescription();
                // 获取当前任务的节点
                String resourceId = task.getTaskDefinitionKey();
                String key = nwfSchemeInfoId + "_" + resourceId + "_" + version;
                XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(key, "7");
                if (xjrBaseTempfield != null && StringUtil.isNotBlank(xjrBaseTempfield.getFvalue()) && !StringUtil.equals(xjrBaseTempfield.getFvalue(), "[]")) {
                    String fvalue = xjrBaseTempfield.getFvalue();
                    List<XjrBaseUser> users = new ArrayList<XjrBaseUser>(10);
                    List<Map<String, Object>> userList = (List<Map<String, Object>>) JSONObject.parse(fvalue);
                    for (Map<String, Object> map : userList) {
                        String fObjType = String.valueOf(map.get("F_ObjType"));
                        String objId = String.valueOf(map.get("F_ObjId"));
                        if (StringUtils.equals(fObjType, "1")) {
                            // 岗位
                            users.addAll(userRelationService.getUsersOfObject(objId, 2));
                        } else if (StringUtils.equals(fObjType, "2")) {
                            // 角色
                            users.addAll(userRelationService.getUsersOfObject(objId, 1));
                        } else if (StringUtils.equals(fObjType, "3")) {
                            // 用户
                            XjrBaseUser xjrBaseUser = userService.getById(objId);
                            users.add(xjrBaseUser);
                        }
                    }
                    //传阅人是否包含登陆者
                    if (!cn.hutool.core.collection.CollectionUtil.contains(users, userService.getById(userId))) {
                        isRights = "0";
                    } else {
                        isRights = "1";
                        schemeName = historicProcessInstance.getProcessDefinitionName();
                        taskName = task.getName();
                        startUser = userService.getById(historicProcessInstance.getStartUserId()).getAccount();
                        createTime = DateUtil.formatDate(historicProcessInstance.getStartTime());
                    }
                } else {
                    isRights = "0";
                }
            }
        }
        HashMap<String, String> result = new HashMap<>();
        result.put("isNormal", isNormal);
        result.put("isApproval", isApproval);
        result.put("isRights", isRights);
        result.put("processInstanceId", processInstanceId);
        result.put("schemeName", schemeName);
        result.put("taskName", taskName);
        result.put("startUser", startUser);
        result.put("createTime", createTime);
        return result;
    }

    @Override
    public boolean changeCandidate(String taskId, String newUserId, String oldUserId) throws Exception {
        JSONObject oldUserMap = new JSONObject();
        oldUserMap.put("F_ObjType", "3");
        oldUserMap.put("F_ObjId", oldUserId);
        JSONArray oldUserArray = new JSONArray();
        oldUserArray.add(oldUserMap);
        //添加新审批人
        boolean multiInstance = FlowableUtil.isMultiInstance(taskId);
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (multiInstance) {
            nwfTaskMapper.updateAssigneeByHi(newUserId, taskId);
            nwfTaskMapper.updateAssigneeByRu(newUserId, taskId);
            nwfTaskMapper.updateAssigneeByHiTask(newUserId, taskId);
            nwfTaskMapper.updateAssigneeByRuTask(newUserId, taskId);
        } else {
            taskService.addCandidateUser(taskId, newUserId);
            //删除旧审批人
            taskService.deleteCandidateUser(taskId, oldUserId);
        }
        //添加传阅任务给旧审批人
        // 任务表单
        String key = task.getProcessInstanceId() + "_" + task.getTaskDefinitionKey();
        XjrBaseTempfield xjrBaseTempfield = new XjrBaseTempfield();
        xjrBaseTempfield.setFkey(key);
        xjrBaseTempfield.setFvalue(oldUserArray.toString());
        xjrBaseTempfield.setType("7");
        xjrBaseTempfieldService.save(xjrBaseTempfield);
        XjrBaseTempfield xjrBaseTempfield1 = new XjrBaseTempfield();
        JSONObject jsonObject = new JSONObject();
        //保存转办信息
        jsonObject.put("oldUserId", oldUserId);
        jsonObject.put("newUserId", newUserId);
        xjrBaseTempfield1.setType("38");
        xjrBaseTempfield1.setFkey(task.getId());
        xjrBaseTempfield1.setFvalue(jsonObject.toJSONString());
        xjrBaseTempfield1.setCreateTime(new Date());
        xjrBaseTempfieldService.save(xjrBaseTempfield1);
        FlowableUtil.createSubTask(taskId, task.getFormKey(), oldUserArray.toString());
        return true;
    }

    @Override
    public boolean againCandidate(JSONArray jsonArray) throws Exception {
        String processInstanceId = "";
        String json = "";
        List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        JSONObject result = new JSONObject();
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            //获取任务id
            String taskId = jsonObject.getString("taskId");
            JSONArray userList = jsonObject.getJSONArray("userList");
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(processInstance.getDeploymentId()).singleResult();
            String nwfSchemeInfoId = processDefinition.getDescription();
            XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
            //查找下个节点的消息策略
            json = xjrNwfScheme.getFjson();
            List<Integer> messageTypes = FlowableUtil.getMessageTypes(task.getTaskDefinitionKey(), json);
            if (CollectionUtil.isNotEmpty(userList)) {
                ArrayList<String> userIds = new ArrayList<>();
                //获取审批人
                for (int j = 0; j < userList.size(); j++) {
                    String userId = userList.getString(j);
                    userIds.add(userId);
                    taskService.addCandidateUser(taskId, userId);
                    //发送审批消息
                }
                SendMessageUtil.sendWorkFlowMessage(task, processInstance.getDeploymentId(), userIds, 1, messageTypes);
            }
        }
        result.put("retCode", 0);
        return true;
    }

    @Override
    public boolean read(String taskId) {
        String userId = SecureUtil.getUserId();
        //获取改任务下的所有传阅任务
        List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery().taskParentTaskId(taskId).taskAssignee(userId).taskName("传阅任务").list();
        for (HistoricTaskInstance historicTaskInstance : taskList) {
            XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(historicTaskInstance.getId(), "35");
            if (xjrBaseTempfield == null) {
                xjrBaseTempfield = new XjrBaseTempfield();
                xjrBaseTempfield.setFvalue("已阅");
                xjrBaseTempfield.setFkey(historicTaskInstance.getId());
                xjrBaseTempfield.setType("35");
                return xjrBaseTempfieldService.save(xjrBaseTempfield);
            }
        }
        return true;
    }


    @Override
    public JSONObject getStartTaskForm(JSONObject keyMap, String formId, String resourceId, String nwfSchemeInfoId, String processInstanceId, String deployId) {
        JSONObject map = new JSONObject();
        // 获取表单信息
        XjrFormSchemeInfo xjrFormSchemeInfo = formSchemeInfoService.getById(formId);
        if (xjrFormSchemeInfo != null) {
            Integer formtype = xjrFormSchemeInfo.getType();
            if (formtype == 2) {
                xjrFormSchemeInfo.setUrlAddress(formSchemeInfoService.getFullUrlOfSystemForm(formId));
            } else {
                String fSchemeid = xjrFormSchemeInfo.getSchemeId();
                // 表单配置
                XjrFormScheme xjrFormScheme = formSchemeService.getById(fSchemeid);
                JSONObject content = JSON.parseObject(xjrFormScheme.getScheme());
                map.put("F_Scheme", content);
            }
            map.put("primaryKey", "");
            // 表单数据
            // 该表单的dataId
            Map<String, Object> formData = null;
            String dataId = "";
            if (StringUtils.equalsIgnoreCase(keyMap.getString("F_FormId"), formId)) {
                dataId = keyMap.getString("F_Id");
                if (formtype == 0) {
                    formData = formSchemeInfoService.getCustomFormData(formId, dataId);
                } else {
                    String urlAddress = keyMap.getString("F_UrlAddress");
                    formData = FlowableUtil.getSystemFormData(dataId, urlAddress);
                }
            }
            //
            String paramInfo = FlowableUtil.getNodeInfo(null, deployId, "28");
            JSONArray formAssignment = new JSONArray();
            if (paramInfo != null) {
                JSONObject jsonObject = JSONObject.parseObject(paramInfo);
                formAssignment = jsonObject.getJSONArray("formAssignment");
            }
            Set<Map.Entry<String, Object>> entrySet = formData.entrySet();
            for (Map.Entry<String, Object> entry : entrySet) {
                // 表名
                String tableName = entry.getKey();
                // 表单数据
                Object object = entry.getValue();
                if (object instanceof HashMap) {
                    // 对象数据类型
                    HashMap record = (HashMap) object;
                    Set<Map.Entry<String, Object>> valueEntrySet = record.entrySet();
                    for (Map.Entry<String, Object> valueEntry : valueEntrySet) {
                        String valueKey = valueEntry.getKey();
                        String key = resourceId + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + tableName + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + valueKey;
                        for (int i = 0; i < formAssignment.size(); i++) {
                            JSONObject jsonObject = formAssignment.getJSONObject(i);
                            JSONObject target = jsonObject.getJSONObject("target");
                            if (StringUtil.equals(key, target.getString("resourceId") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("bindTable") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("id"))) {
                                JSONObject source = jsonObject.getJSONObject("source");
                                HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(source.getString("id")).singleResult();
                                if (variableInstance != null) {
                                    Object value = variableInstance.getValue();
                                    valueEntry.setValue(value);
                                }
                            }
                        }
                    }
                } else if (object instanceof ArrayList) {
                    // 数组类型
                    ArrayList array = (ArrayList) object;
                    for (int j = 0; j < array.size(); j++) {
                        Map<String, Object> newMap = (HashMap) array.get(j);
                        Set<Map.Entry<String, Object>> entrySet1 = newMap.entrySet();
                        for (Map.Entry<String, Object> entry1 : entrySet1) {
                            String valueKey = entry1.getKey();
                            String key = resourceId + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + tableName + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + valueKey;
                            for (int i = 0; i < formAssignment.size(); i++) {
                                JSONObject jsonObject = formAssignment.getJSONObject(i);
                                JSONObject target = jsonObject.getJSONObject("target");
                                if (StringUtil.equals(key, target.getString("resourceId") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("bindTable") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("id"))) {
                                    JSONObject source = jsonObject.getJSONObject("source");
                                    HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(source.getString("id")).singleResult();
                                    if (variableInstance != null) {
                                        Object value = variableInstance.getValue();
                                        entry1.setValue(value);
                                    }
                                }
                            }
                        }
                    }
                } else {
                    XjrNwfScheme nwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
                    if (nwfScheme != null) {
                        JSONObject fjson = JSONObject.parseObject(nwfScheme.getFjson());
                        JSONArray childShapes = fjson.getJSONArray("childShapes");
                        Loop:
                        for (int j = 0; j < childShapes.size(); j++) {
                            JSONObject childShape = childShapes.getJSONObject(j);
                            if (resourceId.equals(childShape.getString("resourceId"))) {
                                JSONArray tableDatas = childShape.getJSONObject("properties").getJSONArray("tableData");
                                for (int k = 0; k < tableDatas.size(); k++) {
                                    JSONObject tableData = tableDatas.getJSONObject(k);
                                    if (formId.equals(tableData.getString("F_Id"))) {
                                        JSONArray childrens = tableData.getJSONArray("children");
                                        for (int l = 0; l < childrens.size(); l++) {
                                            JSONObject children = childrens.getJSONObject(l);
                                            if (tableName.equals(children.getString("fieldsId"))) {
                                                String bindTable = children.getString("bindTable");
                                                String key = resourceId + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + bindTable + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + tableName;
                                                for (int i = 0; i < formAssignment.size(); i++) {
                                                    JSONObject jsonObject = formAssignment.getJSONObject(i);
                                                    JSONObject target = jsonObject.getJSONObject("target");
                                                    if (StringUtil.equals(key, target.getString("resourceId") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("bindTable") + com.xjrsoft.core.tool.utils.StringPool.UNDERSCORE + target.getString("id"))) {
                                                        JSONObject source = jsonObject.getJSONObject("source");
                                                        HistoricVariableInstance variableInstance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(source.getString("id")).singleResult();
                                                        if (variableInstance != null) {
                                                            Object value = variableInstance.getValue();
                                                            entry.setValue(value);
                                                        }
                                                        break Loop;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            map.put("formData", formData);
            // 获取表单的数据
            map.put("primaryKey", dataId);
        }
        return map;
    }

    //自定义查询
    @Override
    public List<TaskVo> queryByParam(String serialNumber, String queryParameter, List<TaskVo> list, JSONArray searchFields) {
        if (StringUtil.isNotBlank(serialNumber)) {
            Pattern pattern = Pattern.compile(serialNumber);
            list = list.stream().filter(s -> {
                Matcher matcher = pattern.matcher(s.getSerialNumber());
                //调用模糊查询方法
                return matcher.find();
            }).collect(Collectors.toList());
        }
        //自定义查询条件
        if (StringUtil.isNotBlank(queryParameter)) {
            JSONObject queryParameterJson = JSONObject.parseObject(queryParameter);
            if (queryParameterJson != null) {
                Set<Map.Entry<String, Object>> entries = queryParameterJson.entrySet();
                for (Map.Entry<String, Object> entry : entries) {
                    String key = entry.getKey();
                    Object valueObj = entry.getValue();
                    String value = String.valueOf(valueObj);
                    if (StringUtil.isNotBlank(value)) {
                        if (StringUtil.endsWithIgnoreCase(key, "_Start")) {
                            //为时间范围查询
                            String field = key.split("_Start")[0];
                            String avueType = "";
                            for (int i = 0; i < searchFields.size(); i++) {
                                JSONObject searchFieldsObj = searchFields.getJSONObject(i);
                                if (StringUtil.equals(searchFieldsObj.getString("name"), field)) {
                                    avueType = searchFieldsObj.getJSONObject("componentConfig").getJSONObject("__config__").getString("avueType");
                                    break;
                                }
                            }
                            //获取结束时间
                            Optional<Map.Entry<String, Object>> endOptional = entries.stream().filter(s -> StringUtil.equalsIgnoreCase(s.getKey(), field + "_End")).findFirst();
                            if (endOptional.isPresent()) {
                                Map.Entry<String, Object> endEntry = endOptional.get();
                                Object endValueObj = endEntry.getValue();
                                if (StringUtil.equals(avueType, "time") || StringUtil.equals(avueType, "datetime")) {
                                    String format = StringUtil.equals(avueType, "time") ? DatePattern.NORM_TIME_PATTERN : DatePattern.NORM_DATE_PATTERN;
                                    //时间选择
                                    list = list.stream().filter(s -> {
                                        String formfilevalue = s.getFormFieldObj().getString(field);
                                        DateTime date = DateUtil.parse(formfilevalue, format);
                                        DateTime startTime = DateUtil.parse(value, format);
                                        DateTime endTime = DateUtil.parse(String.valueOf(endValueObj), format);
                                        return date.isIn(startTime, endTime);
                                    }).collect(Collectors.toList());
                                }
                            }
                        } else if (!StringUtil.endsWithIgnoreCase(key, "_End") && value != null && (!StringUtil.equals(value, "null"))) {
                            Pattern pattern = Pattern.compile(value);
                            list = list.stream().filter(s -> {
                                String formfilevalue = s.getFormFieldObj().getString(key);
                                Matcher matcher = pattern.matcher(formfilevalue == null ? "" : formfilevalue);
                                Optional<Object> searchFieldObj = searchFields.stream().filter(s1 -> StringUtil.equals(((JSONObject) s1).getString("name"), key)).findFirst();
                                if (searchFieldObj.isPresent()) {
//                                    Object o = searchFieldObj.get();
//                                    String avueType = ((JSONObject) o).getJSONObject("componentConfig").getJSONObject("__config__").getString("avueType");
//                                    String type = ((JSONObject) o).getJSONObject("componentConfig").getString("type");
//                                    if (StringUtil.equals(avueType, "input-tip")||StringUtil.equals(type,"number")||StringUtil.equals(avueType,"autoCode")) {
                                    return matcher.find();
//                                    } else {
//                                        return matcher.matches();
//                                    }
                                }
                                return false;
                                //调用模糊查询方法
                            }).collect(Collectors.toList());
                        }
                    }
                }
            }
        }
        return list;
    }

    @Override
    public boolean isCallActivity(String actId, String processDefinitionId, String processInstanceId, Integer type) {
        boolean flag = false;
        if (StringUtil.isNotBlank(actId)) {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
            FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(actId);
            List<SequenceFlow> flows = new ArrayList<>();
            if (type == 1) {
                flows = flowNode.getOutgoingFlows();
            } else {
                flows = flowNode.getIncomingFlows();
            }
            if (CollectionUtil.isNotEmpty(flows)) {
                for (SequenceFlow sequenceFlow : flows) {
                    FlowElement targetFlow = sequenceFlow.getTargetFlowElement();
                    FlowElement sourceFlow = sequenceFlow.getSourceFlowElement();
                    List<HistoricActivityInstance> historicActivityInstances = new ArrayList<>();
                    if (type == 1) {
                        historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(targetFlow.getId()).list();
                    } else {
                        historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).activityId(sourceFlow.getId()).list();
                    }
                    if (CollectionUtil.isNotEmpty(historicActivityInstances)) {
                        HistoricActivityInstance historicActivityInstance = historicActivityInstances.get(0);
                        String activityType = historicActivityInstance.getActivityType();
                        if (StringUtil.equals(activityType, "callActivity")) {
                            return true;
                        } else if ("parallelGateway".equals(activityType) || "exclusiveGateway".equals(activityType) || "scriptTask".equals(activityType)) {
                            flag = isCallActivity(historicActivityInstance.getActivityId(), processDefinitionId, processInstanceId, type);
                        }
                    }
                }
            }
        }
        return flag;
    }

    @Override
    public JSONArray getProcessTask(String taskId, String userId) throws Exception {
        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new Exception("任务不存在");
        }
        String processInstanceId = task.getProcessInstanceId();
        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (historicProcessInstance == null || historicProcessInstance.getEndTime() != null || "删除".equals(historicProcessInstance.getDeleteReason()) || (processInstance != null && processInstance.isSuspended())) {
            throw new Exception("流程已删除或已结束!!");
        }
        //获取当前正在执行的任务之前的节点
        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        Set<HashMap<String, Object>> allNodeSet = new HashSet<>();
        for (Task task1 : taskList) {
            allNodeSet.addAll(FlowableUtil.getAllNode(task1.getTaskDefinitionKey(), processInstanceId, 2, new HashSet<String>()));
        }
        List<HistoricTaskInstance> hitaskList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskAssignee(userId).finished().orderByHistoricTaskInstanceEndTime().asc().list();
        hitaskList.addAll(historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskCandidateUser(userId).finished().orderByHistoricTaskInstanceEndTime().asc().list());
        JSONArray result = new JSONArray();
        if (StringUtil.equalsIgnoreCase(userId, historicProcessInstance.getStartUserId())) {
            String startActivityId = historicProcessInstance.getStartActivityId();
            List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().activityId(startActivityId).processInstanceId(processInstanceId).list();
            //是发起人
            if (CollectionUtil.isNotEmpty(historicActivityInstances)) {
                JSONObject map = new JSONObject();
                map.put("name", historicActivityInstances.get(0).getActivityName());
                map.put("taskId", null);
                map.put("definitionKey", historicActivityInstances.get(0).getActivityId());
                map.put("processInstanceId", processInstanceId);
                map.put("type", "startEvent");
                result.add(map);
            }
        }
        for (HistoricTaskInstance historicTaskInstance : hitaskList) {
            Optional<HashMap<String, Object>> nodeOption = allNodeSet.stream().filter(s -> StringUtil.equals(s.get("activitiId").toString(), historicTaskInstance.getTaskDefinitionKey())).findFirst();
            if (nodeOption.isPresent()) {
                JSONObject map = new JSONObject();
                Integer index = null;
                for (int i = 0; i < result.size(); i++) {
                    if (StringUtil.equals(result.getJSONObject(i).getString("definitionKey"), historicTaskInstance.getTaskDefinitionKey())) {
                        index = i;
                        break;
                    }
                }
                boolean multiInstance = FlowableUtil.isMultiInstance(historicTaskInstance.getId());
                if (!multiInstance) {
                    map.put("name", historicTaskInstance.getName());
                    map.put("taskId", historicTaskInstance.getId());
                    map.put("definitionKey", historicTaskInstance.getTaskDefinitionKey());
                    map.put("processInstanceId", processInstanceId);
                    map.put("type", "userTask");
                    if (index != null) {
                        result.set(index, map);
                    } else {
                        result.add(map);
                    }
                }
            }
        }
        return result;
    }

    @Override
    public JSONObject createprocessForm(String id, String nwfRelationId) throws Exception {
        if (StringUtil.isNotBlank(nwfRelationId) && (!nwfRelationService.checkTemplateAuthority(nwfRelationId, SecureUtil.getUserId())) && (!SecureUtil.isAdminUser())) {
            throw new Exception("没有权限发起改流程!!!");
        }
        JSONObject result = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        String message = "";
        XjrNwfSchemeinfo xjrNwfSchemeinfo = nwfschemeinfoService.getById(id);
        if (xjrNwfSchemeinfo == null || xjrNwfSchemeinfo.getEnabledMark() == 0) {
            throw new Exception("流程已停用,不能发起流程!!!");
        }
        // 重新发起的情况
        String deployId = xjrNwfSchemeinfo.getDeploymentId();
        XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(xjrNwfSchemeinfo.getId());
        String json = "";
        if (xjrNwfScheme != null) {
            json = xjrNwfScheme.getFjson();
        }
        // 根据部署id查询
        // 获取启动流程表单key
        String[] startFormKey = FlowableUtil.readStartForm(deployId);
        if (startFormKey == null) {
            throw new Exception("节点未绑定表单!!!");
        }
        List<XjrFormSchemeInfo> xjrFormSchemeInfos = formSchemeInfoService.listByIds(Arrays.asList(startFormKey));
        if (CollectionUtil.isEmpty(xjrFormSchemeInfos)) {
            throw new Exception("表单不存在!!!");
        }
        Map<String, XjrFormSchemeInfo> xjrFormSchemeInfoMap = xjrFormSchemeInfos.stream().collect(Collectors.toMap(XjrFormSchemeInfo::getId, v -> v));
        List<XjrFormScheme> xjrFormSchemes = formSchemeService.listByIds(xjrFormSchemeInfos.stream().map(XjrFormSchemeInfo::getSchemeId).collect(Collectors.toSet()));
        Map<String, XjrFormScheme> xjrFormSchemeMap = xjrFormSchemes.stream().collect(Collectors.toMap(XjrFormScheme::getId, v -> v));
        //获取节点的流程参数信息
        String paramInfo = FlowableUtil.getNodeInfo(null, deployId, "28");
        JSONArray formAssignments = new JSONArray();
        JSONArray processParameters = new JSONArray();
        if (paramInfo != null) {
            JSONObject jsonObject = JSONObject.parseObject(paramInfo);
            formAssignments = jsonObject.getJSONArray("formAssignment");
        }
        //获取所有流程参数
        if (StringUtil.isNotBlank(json)) {
            JSONObject jsonObject = JSONObject.parseObject(json);
            JSONObject properties = jsonObject.getJSONObject("properties");
            processParameters = properties.getJSONArray("parameters");
        }
        // 获取当前节点信息
        JSONArray nodeInfoArray = JSONArray.parseArray(FlowableUtil.getNodeInfo(null, deployId, "3"));
        for (String formId : startFormKey) {
            XjrFormSchemeInfo xjrFormSchemeinfo = xjrFormSchemeInfoMap.get(formId);
            if (xjrFormSchemeinfo == null) {
                throw new Exception("表单不存在!!!");
            }
            JSONObject jsonObject = new JSONObject();
            // 获取开始节点的表单字段信息
            // 表单字段信息
            Set<Object> objectSet = formAssignments.stream().filter(s -> StringUtil.equals(((JSONObject) s).getJSONObject("target").getString("formId"), formId)).collect(Collectors.toSet());
            Map<String, Object> customizedFormData = new HashMap<>();
            for (Object obj : objectSet) {
                JSONObject formAssignmentObj = (JSONObject) obj;
                JSONObject target = formAssignmentObj.getJSONObject("target");
                JSONObject source = formAssignmentObj.getJSONObject("source");
                String bindTable = target.getString("bindTable");
                Object o = customizedFormData.get(bindTable);
                Map<String, Object> valueMap = new HashMap<>();
                if (o != null) {
                    valueMap = (Map<String, Object>) o;
                }
                String paramId = source.getString("id");
                Optional<Object> paramOptional = processParameters.stream().filter(s -> StringUtil.equals(((JSONObject) s).getString("id"), paramId)).findFirst();
                if (paramOptional.isPresent()) {
                    JSONObject paramObj = (JSONObject) paramOptional.get();
                    //获取参数值
                    try {
                        String value = FlowableUtil.getGobalParams(xjrNwfSchemeinfo, paramObj, null);
                        if (StringUtil.isNotBlank(value) && StringUtil.isNumeric(value)) {
                            valueMap.put(target.getString("fieldsId"), Integer.valueOf(value));
                        } else {
                            valueMap.put(target.getString("fieldsId"), value);
                        }
                    } catch (Exception e) {
                        message = e.getMessage();
                    }
                }
                if (o == null) {
                    customizedFormData.put(target.getString("bindTable"), valueMap);
                }
            }
            jsonObject.put("parameter", customizedFormData);
            if (CollectionUtil.isNotEmpty(nodeInfoArray)) {
                for (int i = 0; i < nodeInfoArray.size(); i++) {
                    JSONObject nodeInfo = nodeInfoArray.getJSONObject(i);
                    if (StringUtil.equals(formId, nodeInfo.getString("F_Id"))) {
                        String fId = nodeInfo.getString("F_Id");
                        XjrFormSchemeInfo formSchemeInfo = formSchemeInfoService.getById(fId);
                        if (formSchemeInfo != null) {
                            nodeInfo.put("F_Url", formSchemeInfoService.getFullUrlOfSystemForm(formSchemeInfo.getId()));
                        }
                        jsonObject.put("formFieldInfo", nodeInfo);
                        break;
                    }
                }
            }
            Integer type = xjrFormSchemeinfo.getType();
            if (type == 0) {
                String fSchemeid = xjrFormSchemeinfo.getSchemeId();
                XjrFormScheme xjrFormScheme = xjrFormSchemeMap.get(fSchemeid);
                jsonObject.put("F_Scheme", JSON.parseObject(xjrFormScheme.getScheme()));
            } else if (type == 2) {
                xjrFormSchemeinfo.setUrlAddress(formSchemeInfoService.getFullUrlOfSystemForm(formId));
            }
            jsonObject.put("SchemeInfo", BeanUtil.copy(xjrFormSchemeinfo, FormSchemeInfoVo.class));
            // 验证是否关联其他流程
            if (StringUtil.isNotBlank(json)) {
                JSONObject configJson = JSON.parseObject(json);
                jsonObject.put("relevanceTask", configJson.getJSONObject("properties").getJSONObject("relevanceTask"));
            }
            jsonArray.add(jsonObject);
        }
        result.put("formDate", jsonArray);
        result.put("message", message);
        return result;
    }


    @Override
    @Transactional
    public List<JSONObject> getAllProcessId(String deploymentId) throws Exception {
        // 根据deploymentId获取nwfschemeinfoId
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
        List<JSONObject> processObjList = new ArrayList<>();
        if (definition != null) {
            String nwfSchemeInfoId = definition.getDescription();
            XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
            JSONArray changedChildShapes = null;
            XjrBaseTempfield tempKeyValue = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + "_" + deploymentId, "30");
            String changedJson = null;
            if (tempKeyValue != null) {
                changedJson = tempKeyValue.getFvalue();
                JSONObject changedJsonObj = (JSONObject) JSON.parse(changedJson);
                changedChildShapes = (JSONArray) changedJsonObj.get("childShapes");
            }
            List<Deployment> deploymentList = repositoryService.createDeploymentQuery().processDefinitionKey(definition.getKey()).list();
            if (CollectionUtil.isNotEmpty(deploymentList)) {
                for (Deployment deployment : deploymentList) {
                    if (StringUtil.equals(deploymentId, deployment.getId())) {
                        //为当前要修改的版本
                        continue;
                    }
                    // 当前任务的json
                    String currentDeploymentId = deployment.getId();
                    // 2.取当前任务之前的任务集合
                    List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().deploymentId(currentDeploymentId).list();
                    if (CollectionUtil.isNotEmpty(processInstanceList)) {
                        for (ProcessInstance processInstance : processInstanceList) {
                            // 流水号
                            String serialNumber = "";
                            XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(processInstance.getProcessInstanceId(), "19");
                            if (xjrTempKeyvalue != null) {
                                serialNumber = xjrTempKeyvalue.getFvalue();
                            }
                            if (!processInstance.isSuspended()) {
                                //流程没有挂起
                                JSONObject processObj = new JSONObject();
                                processObj.put("processInstanceId", processInstance.getProcessInstanceId());
                                processObj.put("deploymentId", deploymentId);
                                processObj.put("serialNumber", serialNumber);
                                processObj.put("processInstanceName", processInstance.getName());
                                processObj.put("status", 0);
                                processObj.put("description", "");
                                processObjList.add(processObj);
                            }
                        }
                    }
                }
            }
            // 修改流程的部署ID
            nwfSchemeInfoService.updateDeploymentId(nwfSchemeInfoId, deploymentId);
            if (xjrNwfScheme != null) {
                XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + "_" + deploymentId, "31");
                if (xjrBaseTempfield != null) {
                    xjrNwfScheme.setContent(xjrBaseTempfield.getFvalue());
                }
                xjrNwfScheme.setFjson(changedJson);
                if (nwfSchemeService.updateById(xjrNwfScheme)) {
                    nwfSchemeAuthService.saveAuthList(nwfSchemeInfoId, JSONObject.parseObject(changedJson).getJSONObject("properties").getJSONArray("schemeAuthList"));
                }
            }
        }
        return processObjList;
    }


    @Override
    public synchronized JSONObject changeProcessVersion(String deploymentId, String processInstanceId) throws Exception {
        // 根据deploymentId获取nwfschemeinfoId
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
        String nwfSchemeInfoId = definition.getDescription();
        String serialNumber = "";
        String processInstanceName = "";
        Integer status = 0;
        String description = "";
        //变更信息
        JSONObject result = new JSONObject();
        // 流水号
        XjrBaseTempfield xjrTempKeyvalue = xjrBaseTempfieldService.getByIdAndType(processInstanceId, "19");
        if (xjrTempKeyvalue != null) {
            serialNumber = xjrTempKeyvalue.getFvalue();
        }
        if (processInstance != null) {
            // 1.获取当前版本json和要替换版本的json
            // 替换后的json
            Set<String> processInstanceIds = new HashSet<>();
            processInstanceIds.add(processInstanceId);
            List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().superProcessInstanceId(processInstanceId).list();
            processInstanceIds.addAll(processInstanceList.stream().map(Execution::getProcessInstanceId).collect(Collectors.toSet()));
            processInstanceName = processInstance.getName();
            JSONArray changedChildShapes = null;
            XjrBaseTempfield tempKeyValue = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + "_" + deploymentId, "30");
            String changedJson = null;
            JSONObject changedJsonObj = null;
            if (tempKeyValue != null) {
                changedJson = tempKeyValue.getFvalue();
                changedJsonObj = (JSONObject) JSON.parse(changedJson);
                changedChildShapes = (JSONArray) changedJsonObj.get("childShapes");
            }
            // 当前任务的json
            JSONArray currentChildShapes = null;
            JSONObject currentJsonobj = null;
            String currentDeploymentId = processInstance.getDeploymentId();
            XjrBaseTempfield currentTempKeyValue = xjrBaseTempfieldService.getByIdAndType(nwfSchemeInfoId + "_" + currentDeploymentId, "30");
            if (currentTempKeyValue != null) {
                String currentJson = currentTempKeyValue.getFvalue();
                currentJsonobj = (JSONObject) JSON.parse(currentJson);
                currentChildShapes = (JSONArray) currentJsonobj.get("childShapes");
            }
            //对比流程属性
            JSONObject jsonObject = FlowableUtil.compareProperties(currentJsonobj.getJSONObject("properties"), changedJsonObj.getJSONObject("properties"), processInstance.getStartUserId());
            Boolean isSame = jsonObject.getBoolean("isSame");
            String information = jsonObject.getString("information");
            // 获取流程实例
            // 流程发起人
            String startUserId = processInstance.getStartUserId();
            XjrBaseUser startUser = userService.getById(startUserId);
            // 业务主键
            String businessKey = processInstance.getBusinessKey();
            // 3.如果开始节点一样,则发起新的流程
            XjrNwfScheme xjrNwfScheme = nwfSchemeService.getBySchemeInfoId(nwfSchemeInfoId);
            if (isSame) {
                //从开始节点开始对比
                List<String> eqResourceIds = new ArrayList<>();
                String startResourceId = null;
                for (int i = 0; i < changedChildShapes.size(); i++) {
                    JSONObject changedChildShapeJsonObject = changedChildShapes.getJSONObject(i);
                    String type = changedChildShapeJsonObject.getJSONObject("properties").getString("type");
                    if (StringUtil.equals(type, "bpmn:StartEvent")) {
                        startResourceId = changedChildShapeJsonObject.getString("resourceId");
                        //获取json中相等的节点的id
                        List<ActivityInstance> activityInstanceList = runtimeService.createActivityInstanceQuery().processInstanceId(processInstanceId).unfinished().list();
                        Set<String> activityIds = new HashSet<>();
                        //获取当前流程正在运行的任务之前的节点
                        if (CollectionUtil.isNotEmpty(activityInstanceList)) {
                            for (ActivityInstance activityInstance : activityInstanceList) {
                                activityIds = FlowableUtil.getNode(activityInstance.getActivityId(), processInstanceId, 2, new HashSet<String>());
                            }
                        }
                        eqResourceIds = FlowableUtil.compareNode(currentChildShapes, changedChildShapes, startResourceId, new ArrayList<String>(), activityIds);
                    }
                }
                if (eqResourceIds.contains(startResourceId)) {
                    boolean flag = true;
                    String taskName = "";
                    Map<String, Object> retMap = FlowableUtil.startProcessInstance(deploymentId, startUser.getUserId(), businessKey, xjrNwfScheme);
                    String newProcessInsId = (String) retMap.get("processInstanceId");
                    HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(newProcessInsId).singleResult();
                    HistoricActivityInstance historicActivityInstance = historyService.createHistoricActivityInstanceQuery().processInstanceId(newProcessInsId).activityId(historicProcessInstance.getStartActivityId()).singleResult();
                    if (historicActivityInstance != null) {
                        String activityName = historicActivityInstance.getActivityName();
                        taskName = StringUtil.isBlank(activityName) ? "开始" : activityName;
                    }
                    while (flag) {
                        flag = false;
                        List<Task> taskList = taskService.createTaskQuery().processInstanceId(newProcessInsId).list();
                        for (Task task : taskList) {
                            if (eqResourceIds.contains(task.getTaskDefinitionKey())) {
                                XjrBaseTempfield xjrBaseTempfield = xjrBaseTempfieldService.getByIdAndType(processInstanceId + StringPool.UNDERSCORE + task.getTaskDefinitionKey(), "32");
                                if (xjrBaseTempfield != null) {
                                    JSONObject paramMap = JSONObject.parseObject(xjrBaseTempfield.getFvalue());
                                    paramMap.put("taskId", task.getId());
                                    // 完成任务
                                    String assignee = null;
                                    List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskDefinitionKey(task.getTaskDefinitionKey()).orderByHistoricTaskInstanceStartTime().desc().list();
                                    if (CollectionUtil.isNotEmpty(list)) {
                                        HistoricTaskInstance historicTaskInstance = list.get(0);
                                        if (historicTaskInstance != null) {
                                            assignee = historicTaskInstance.getAssignee();
                                        }
                                    }
                                    FlowableUtil.completeTask(assignee, paramMap);
                                    flag = true;
                                }
                            }
                        }
                        List<Task> newtasklist = taskService.createTaskQuery().processInstanceId(newProcessInsId).list();
                        if(CollectionUtil.isNotEmpty(newtasklist)){
                            Task task = newtasklist.get(0);
                            String name = task.getName();
                            taskName = StringUtil.isBlank(name) ? "用户任务" : name;
                        }
                    }

                    status = 1;
                    description = "流程已变更至" + taskName + "节点";
                    // 删除之前流程和调用的子流程
                    for (String processId : processInstanceIds) {
                        FlowableUtil.deleteProcessInstance(processId);
                    }
                } else {
                    status = 0;
                    description = "因在流程版本数据对比中，开始节点数据存在修改，流程任务结束";
                    //挂起流程
                    for (String processId : processInstanceIds) {
                        FlowableUtil.suspendProcessInstance(processId, "流程版本变更时，开始节点被修改", 0);
                    }
                }
            } else {
                status = 0;
                description = information;
                //挂起流程
                for (String processId : processInstanceIds) {
                    FlowableUtil.suspendProcessInstance(processId, information, 0);
                }
            }
        } else {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            processInstanceName = historicProcessInstance.getName();
            status = 0;
            description = "流程已结束或者已被关闭";
        }
        result.put("processInstanceId", processInstanceId);
        result.put("deploymentId", deploymentId);
        result.put("serialNumber", serialNumber);
        result.put("processInstanceName", processInstanceName);
        result.put("status", status);
        result.put("description", description);
        return result;
    }

    @Override
    public List<String> getUserIdByTask(String taskId) {
        return nwfTaskMapper.getUserIdByTask(taskId);
    }

    @Override
    public String deleteUselessDate() {
        //获取所有的流程模板
        List<XjrNwfSchemeinfo> nwfSchemeinfos = nwfschemeinfoService.list();
        QueryWrapper<XjrBaseTempfield> query = new QueryWrapper<>();
        if (CollectionUtil.isNotEmpty(nwfSchemeinfos)) {
            for (XjrNwfSchemeinfo xjrNwfSchemeinfo : nwfSchemeinfos) {
                String nwfSchemeInfoId = xjrNwfSchemeinfo.getId();
                ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(xjrNwfSchemeinfo.getDeploymentId()).singleResult();
                List<Deployment> deploymentList = repositoryService.createDeploymentQuery().processDefinitionKey(definition.getKey()).list();
                List<String> deploymentIds = deploymentList.stream().map(s -> s.getId()).collect(Collectors.toList());
                // 删除流程在tempkeyvalue表中的数据
                query.lambda().notLike(StringUtils.isNotBlank(nwfSchemeInfoId), XjrBaseTempfield::getFkey, nwfSchemeInfoId);
                if (CollectionUtil.isNotEmpty(deploymentIds)) {
                    for (String deploymentId : deploymentIds) {
                        query.lambda().notLike(StringUtils.isNotBlank(deploymentId), XjrBaseTempfield::getFkey, deploymentId);
                    }
                }
                //获取当前模板下的流程
                List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().deploymentIdIn(deploymentIds).list();
                if (CollectionUtil.isNotEmpty(list)) {
                    for (HistoricProcessInstance processInstance : list) {
                        if (processInstance.getDeleteReason() == null) {
                            query.lambda().notLike(XjrBaseTempfield::getFkey, processInstance.getId());
                        }
                    }
                }
            }
        }
        query.lambda().or().eq(XjrBaseTempfield::getFvalue, "[]").or().eq(XjrBaseTempfield::getFvalue, null).or().eq(XjrBaseTempfield::getFvalue, "");
        int count = xjrBaseTempfieldService.count(query);
        boolean remove = xjrBaseTempfieldService.remove(query);
        return "清除了" + count + "条无用数据";
    }

    public static void transFormListData(List<TaskVo> list, JSONArray formFields) {
        Map<String, List<Object>> fieldValueListMap = new CaseInsensitiveKeyMap<>();
        for (TaskVo taskVo : list) {
            JSONObject formFieldObj = taskVo.getFormFieldObj();
            for (Map.Entry<String, Object> entry : formFieldObj.entrySet()) {
                Object value = entry.getValue();
                if (StringUtil.isEmpty(value)) {
                    continue;
                }
                if (value instanceof NCLOB) {
                    try {
                        value = ((NCLOB) value).stringValue();
                    } catch (SQLException e) {
                        log.error("NCLOB类型数据序列化失败！", e);
                    }
                }
                String key = entry.getKey();
                List<Object> values = fieldValueListMap.get(key);
                if (values == null) {
                    values = new ArrayList<>();
                    fieldValueListMap.put(key, values);
                }
                values.add(value);
            }
        }
        Map<String, Map<String, Object>> dataMap = new HashMap<>(16);
        Map<String, String> multiValueSeparatorMap = new HashMap<>();
        for (Object formField : formFields) {
            JSONObject field = (JSONObject) formField;
            JSONObject componentConfig = field.getJSONObject(FormConstants.COMPONENTCONFIG);
            String fieldName = MapUtils.getString(field, FormConstants.DB_TABLE_NAME);
            if (componentConfig != null) {
                FormDataUtil.buildFieldData(dataMap, multiValueSeparatorMap, componentConfig, fieldValueListMap, fieldName);
            }
        }
        for (TaskVo taskVo : list) {
            JSONObject formFieldObj = taskVo.getFormFieldObj();
            for (String fieldName : dataMap.keySet()) {
                Object value = formFieldObj.get(fieldName);
                if (value instanceof CLOB) {
                    try {
                        value = ((NCLOB) value).stringValue();
                    } catch (SQLException e) {
                        log.error("NCLOB类型数据序列化失败！", e);
                    }
                } else {
                    value = StringUtil.isEmpty(formFieldObj.get(fieldName)) ? null : String.valueOf(value);
                }
                Map<String, Object> data = dataMap.get(fieldName);
                if (data == null || StringUtil.isEmpty(value)) {
                    continue;
                }
                Object transToValue = null;
                if (multiValueSeparatorMap.keySet().contains(fieldName)) {
                    String[] values = StringUtils.split(String.valueOf(value), StringPool.COMMA);
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < values.length; i++) {
                        Object obj = data.get(values[i]);
                        if (obj != null) {
                            if (i != 0) {
                                sb.append(multiValueSeparatorMap.get(fieldName));
                            }
                            sb.append(obj);
                        }
                    }
                    transToValue = sb.toString();
                } else {
                    transToValue = data.get(value);
                }
                if (!(transToValue == null || "".equals(transToValue))) {
                    formFieldObj.put(fieldName, transToValue);
                }
            }
        }
    }
}
